0

Zig-Zag Traversal

I was trying to follow "On the Hardware Implementation of Triangle Traversal Algorithms for Graphics Processing" (Royer, Ituero, Lopez-Vallejo, & Barrio) (page 4) to implement Zig-Zag traversal algorithm for triangle triversal/rasterization. However, the explanation in the paper is counter-intuitive for me and I was not able to make it work.

I tried to implement a finite state machine but I can't quite figure out the exact states. For now, I'm having (direction, e_1, e_2, e_3) where e_n represent edge test output for each edge. Pseudo code:

if (right, true, true, true):
    x++;  // Move towards right
else if (left, true, true, true):
    x--;  // Move towards left
else:
    // This is where I stuck. There should be two cases where in one of them
    // y goes down and x doesn't change direction, in the other case x simply
    // flips its direction. But I wasn't able to figure it out.

Any help would be appreciated!

Edit: My effort so far: While the edge test is working correctly, only few parts of the graph was rasterized.

/// Zig Zag (not working)
int top_row = floor(fmin(y0, fmin(y1, y2)));
int bot_row = floor(fmax(y0, fmax(y1, y2)));
if (y0 > y1) {
  swap(x0, x1); swap(y0, y1);
}
if (y0 > y2) {
  swap(x0, x2); swap(y0, y2);
}
if (y1 > y2) {
  swap(x1, x2); swap(y1, y2);
}
assert(top_row == floor(y0));
assert(bot_row == floor(y2));

bool direction = true;
bool changed = false;
int x = floor(x0); int y = floor(y0);
while (y <= bot_row) {
  bool e1, e2, e3;
  e1 = edge_test((float)x+0.5, (float)y+0.5, x0, y0, x1, y1) < 0.0f;
  e2 = edge_test((float)x+0.5, (float)y+0.5, x1, y1, x2, y2) < 0.0f;
  e3 = edge_test((float)x+0.5, (float)y+0.5, x2, y2, x0, y0) < 0.0f;

  if ((e1 == e2) && (e2 == e3)) {
    if ( x < 0 || x >= width ) continue;
    if ( y < 0 || y >= height ) continue;
    samplebuffer[y][x].fill_pixel(color);

    if (direction) x++;
    else x--;
  } else if (changed) {
    y++;
    changed = false;
  } else {
    direction = !direction;
    changed = true;
    if (direction) x++;
    else x--;
  }
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
Provi
  • 66
  • 9

1 Answers1

0

How I see state machine:

Dir = +1 / -1

State 0: (moving inside)
EdgeTest: 
    0 => State 1 ;  y++
    1 => State 0 ;  x = x + Dir

State 1: (outside)
EdgeTest: 
    0 => State 3 ;  Dir = - Dir
    1 => State 2 ;

State 2: (inside moving the same dir)
EdgeTest: 
    0 => State 3 ;  Dir = - Dir
    1 => State 2 ;  x= x + Dir

State 3: (outside)
EdgeTest: 
    0 => State 3 ; x = x + Dir
    1 => State 0 ; 
MBo
  • 77,366
  • 5
  • 53
  • 86
  • 1
    I tried to implement this and it seems that it works for common cases. However, for some edge cases like imagine two vertically stacked pixel say $p_1$, $p_2$, and the triangle is so thin that its two edges pass through between $x_1 + 0.5, y_1 + 0.5$ and $x_2 + 0.5, y_2 + 0.5$. The edge test of both pixel would fail, and when (x,y) goes from $p_1$ to $p_2$, state_1 is triggered and the direction is inverted, possibly causing x to keep adding itself away from the triangle. How do I deal with this? – Provi Feb 11 '17 at 05:28