Jump to content

  • Log In with Google      Sign In   
  • Create Account


Problem with shaded triangle


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 arnsa   Members   -  Reputation: 127

Like
0Likes
Like

Posted 07 October 2012 - 08:00 AM

Hello, I was trying to draw a shaded triangle, but I get wrong colors. Here's the example of what I get, if I call a function with red, green and blue colors:

Posted Image

Code's here:

unsigned RGB(unsigned char R, unsigned char G, unsigned B){
	return  (R << 16) | (G << 8) | B;
}
void put_pixel(SDL_Surface * s, unsigned x, unsigned y, unsigned color){
	unsigned long * pixels = (unsigned long *)s->pixels;
	if(x >= s->w || y >= s->h)
		return;
	pixels[x+y*s->w] = color;
}
void draw_line(SDL_Surface * s, int x0, int y0, int x1, int y1, unsigned color){
	int x, y;
	int xproj = x1-x0, yproj = y1-y0, pm;
	if(!xproj && !yproj)
		return;
  
	if(abs(xproj) > abs(yproj)){
		pm = xproj >= 0 ? 1 : -1;
		for(x = 0; x != xproj; x += pm){
			y = rint(x* yproj/(double)xproj);
			put_pixel(s, x0 + x, y0 + y, color);
		}
	}else{
		pm = yproj >= 0 ? 1 : -1;
		for(y = 0; y != yproj; y += pm){
			x = rint(y* xproj/(double)yproj);
			put_pixel(s, x0+x, y0+y, color);
		}
	}
}
float sign(int x0, int y0, int x1, int y1, int x2, int y2){
	return (x0 - x2) * (y1 - y2) - (x1 - x2) * (y0 - y2);
}
int ptintr(int sx, int sy, int x0, int y0, int x1, int y1, int x2, int y2){
	int b1, b2, b3;
  
	b1 = sign(sx, sy, x0, y0, x1, y1) < 0.0f ? 1 : 0;
	b2 = sign(sx, sy, x1, y1, x2, y2) < 0.0f ? 1 : 0;
	b3 = sign(sx, sy, x2, y2, x0, y0) < 0.0f ? 1 : 0;
	if((b1 == b2) && (b2 == b3))
		return 1;
	return 0;
}
float get_dist(int x1, int y1, int x2, int y2){
	int xproj = x2-x1;
	int yproj = y2-y1;
	float dist = sqrt(pow(xproj, 2) + pow(yproj, 2));
	return dist;
}
unsigned char getR(unsigned c){
	return (c >> 16) & 0xFF;
}
unsigned char getG(unsigned c){
	return (c >> 8) & 0xFF;
}
unsigned char getB(unsigned c){
	return c & 0xFF;
}
void draw_ftriangle(SDL_Surface * s, int x0, int y0, unsigned c0, int x1, int y1, unsigned c1, int x2, int y2, unsigned c2){
	int x;
	signed d0, d1, d2;
	unsigned R, G, B, color;
	int ymin = min(y0, min(y1, y2));
	int xmin = min(x0, min(x1, x2));
	int ymax = max(y0, max(y1, y2));
	int xmax = max(x0, max(x1, x2));
	draw_line(s, x0, y0, x1, y1, color);
	draw_line(s, x1, y1, x2, y2, color);
	draw_line(s, x0, y0, x2, y2, color);
	for(; ymin < ymax; ymin++)
		for(x=xmin; x < xmax; x++)
			if(ptintr(x, ymin, x0, y0, x1, y1, x2, y2)){
				d0 = get_dist(x, ymin, x0, y0);
				d1 = get_dist(x, ymin, x1, y1);
				d2 = get_dist(x, ymin, x2, y2);
				R = d0+d1+d2 == 1 ? getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2 :
									 (getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2)/(d0+d1+d2);
				G = d0+d1+d2 == 1 ? getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2 :
									(getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2)/(d0+d1+d2);
				B = d0+d1+d2 == 1 ? getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2 :
									(getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2)/(d0+d1+d2);
				color = RGB(R, G, B);
				put_pixel(s, x, ymin, color);
			}
}

And I call function draw_ftriangle like this:

		draw_ftriangle(surface, 100, 100, RGB(255, 0, 0),
								235, 150, RGB(0, 255, 0),
								64, 254, RGB(0, 0, 255));

I'm not sure, but I think the problem is here:

				R = d0+d1+d2 == 1 ? getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2 :
									 (getR(c0)*d0 + getR(c1)*d1 + getR(c2)*d2)/(d0+d1+d2);
				G = d0+d1+d2 == 1 ? getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2 :
									(getG(c0)*d0 + getG(c1)*d1 + getG(c2)*d2)/(d0+d1+d2);
				B = d0+d1+d2 == 1 ? getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2 :
									(getB(c0)*d0 + getB(c1)*d1 + getB(c2)*d2)/(d0+d1+d2);

Please help me to find a problem! Posted Image

Edited by arnsa, 07 October 2012 - 08:02 AM.


Sponsor:

#2 Ignifex   Members   -  Reputation: 507

Like
0Likes
Like

Posted 09 October 2012 - 04:44 AM

I first noticed that your triangle is not interpolating between red, green and blue, but between cyan, magenta en yellow. So somewhere your colors are being "reversed".

Your problem is indeed in the code fragment you have shown below. The interpolation between corner points does not depend linearly on the distance, but the inverse of it. If the distance to your red point (d0) is very small, your "red weight" should be high.

You can have a look at Barycentric coordinates, which seem to most closely match what you are doing.

Edited by Ignifex, 09 October 2012 - 04:48 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS