Wu lines

Started by
4 comments, last by GarlandIX 21 years, 10 months ago
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.
------------------------------BASIC programmers don't die, they just GOSUB and don't return.
Advertisement
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...
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.
------------------------------BASIC programmers don't die, they just GOSUB and don't return.
grad = dy/dx;

Should be:

grad = (float)dy / dx;

Otherwise you perform integer division, which you don''t want.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files ]
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.
------------------------------BASIC programmers don't die, they just GOSUB and don't return.
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.

This topic is closed to new replies.

Advertisement