Archived

This topic is now archived and is closed to further replies.

GarlandIX

Wu lines

Recommended Posts

Okay, after reding the tutorial on Wu anti-aliased lines on this site, i attempted to convert it to C++ code so I could use it in a DirectDraw Game i am making. The problem is, it doesn''t work! It doesn''t draw the lines properly! It draws them horizontally or vertically when it should be diagonal. Here is the relevant code:
  
inline void PlotPixel(int x, int y, WORD color)
{
  if(x>=0 && x<=640 && y>=0 && y<=480)
    video_buffer[x+y*mempitch] = color;
}
void DrawLine(int x1, int y1, int x2, int y2, WORD color)
{
  float grad, length, xm, ym,
		xgap, ygap, xend, yend, xf, yf,
		brightness1, brightness2;
  int dx, dy, x, y, ix1, ix2, iy1, iy2;
  WORD c1, c2;

  dx = x2-x1;
  dy = y2-y1;
  if (fabs(dx) > fabs(dy)) // x major

  {
    if (x1 > x2)
    {
      swap(x1,x2);
      swap(y1,y2);
      dx = x2-x1;
      dy = y2-y1;
    }
    grad = dy/dx; //gradient of the line(slope, i think)

    xend = x1;
    yend = y1 + grad*x1;
    xgap = invfrac(x1+0.5);
    ix1 = (int)xend;
    iy1 = (int)yend;
    brightness1 = invfrac(yend) * xgap;
    brightness2 =    frac(yend) * xgap;
    c1 = (WORD)brightness1*color;
    c2 = (WORD)brightness2*color;
    PlotPixel(ix1,iy1,c1);
    PlotPixel(ix1,iy1+1,c2);
    yf = yend+grad;

    xend = x2;
    yend = y2 + grad*(xend-x2);
    xgap = invfrac(x2-0.5);
    ix2 = (int)xend;
    iy2 = (int)yend;
    brightness1 = invfrac(yend) * xgap;
    brightness2 =    frac(yend) * xgap;
    c1 = (WORD)brightness1*color;
    c2 = (WORD)brightness2*color;
    PlotPixel(ix2,iy2,c1);
    PlotPixel(ix2,iy2+1,c2);

    for (x = ix1+1; x <= ix2-1; x++)
    {
      brightness1 = invfrac(yf);
      brightness2 =    frac(yf);
      c1 = (WORD)brightness1*color;
      c2 = (WORD)brightness2*color;
      PlotPixel(x,(int)yf,c1);
      PlotPixel(x,(int)yf+1,c2);
      yf = yf + grad;
    }
  }
  else // y major

  {
    if (y1 > y2)
    {
      swap(x1,x2);
      swap(y1,y2);
      dx = x2-x1;
      dy = y2-y1;
    }
    grad = dx/dy;

    yend = y1;
    xend = x1 + grad*(yend-y1);
    ygap = invfrac(y1+0.5);
    ix1  = (int)xend;
    iy1  = (int)yend;
    brightness1 = invfrac(xend) * ygap;
    brightness2 =    frac(xend) * ygap;
    c1 = (WORD)brightness1*color;
    c2 = (WORD)brightness2*color;
    PlotPixel(ix1,iy1,c1);
    PlotPixel(ix1+1,iy1,c2);
    xf = xend+grad;

    yend = y2;
    xend = x2 + grad*(yend-y2);
    ygap = invfrac(y2+0.5);
    ix2  = (int)xend;
    iy2  = (int)yend;
    brightness1 = invfrac(xend) * ygap;
    brightness2 =    frac(xend) * ygap;
    c1 = (WORD)brightness1*color;
    c2 = (WORD)brightness2*color;
    PlotPixel(ix2,iy2,c1);
    PlotPixel(ix2+1,iy2,c2);

    for (y = iy1+1; y <= iy2-1; y++)
    {
      brightness1 = invfrac(xf);
      brightness2 =    frac(xf);
      c1 = (WORD)brightness1*color;
      c2 = (WORD)brightness2*color;
      PlotPixel((int)xf,y,c1);
      PlotPixel((int)xf+1,y,c2);
      xf = xf + grad;
    }
  }//endif

}
//Name: swap Purpose: Swaps two variables in place

inline void swap(int a, int b)
{
  a = a ^ b;
  b = a ^ b;
  a = a ^ b;
}

//Name: trunc Purpose returns the integer part of x

inline int trunc(float x)
{
  return (int)x;
}

//Name: frac Purpose returns the fractional part of x

inline float frac(float x)
{
  return x - (int)x;
}

//Name: invfrac Purpose returns 1-(the fractional part of x)

inline float invfrac(float x)
{
  return 1-(x-((int)x));
}
  
video_buffer and mempitch are globals that I set after I lock the surface. ------------------------------ BASIC programmers don''t die, they just GOSUB and don''t return.

Share this post


Link to post
Share on other sites
Without reading too hard, I find that your swap() looks bad.
How do you expect it to work? You must pass the values by reference if you want the values to be swapped for the calling function...

Share this post


Link to post
Share on other sites
quote:
Original post by amag
Without reading too hard, I find that your swap() looks bad.
How do you expect it to work? You must pass the values by reference if you want the values to be swapped for the calling function...


yes, i know. I noticed that about 5 seconds after i posted and changed it. That did not help much though.

------------------------------
BASIC programmers don''t die, they just GOSUB and don''t return.

Share this post


Link to post
Share on other sites
Kylotan: That helped(can''t beleive i didn''t see it ), but now the line draws sort of like this: (sorry for the crappy diagram)

.
.

.



.


Also, does anyone know any other websites or tutorials that have info on Wu anti-aliased lines (preferably with C/C++ code)?

------------------------------
BASIC programmers don''t die, they just GOSUB and don''t return.

Share this post


Link to post
Share on other sites
You wrote:

xend = x1;
yend = y1 + grad * x1;

And it should be:

xend = trunc(x1+.5)
yend = y1 + grad * (xend-x1)

See the difference? you multiply grad by x1, which might give a BIG number! All they wanna do, is add a little to yend. If you don''t want that + 0.5, you can just assign y1 to yend.

Share this post


Link to post
Share on other sites