summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@l3000.localdomain>2010-12-20 20:26:52 -0500
committerSøren Sandmann Pedersen <ssp@l3000.localdomain>2010-12-20 20:26:52 -0500
commit182ca6b7ab15720e810148bc5315b12a73e9b449 (patch)
tree8669a46fc51338062261ac77ed743c396bbb7ca5
parent193100012641e494ae0c08eb24114dd40d60b3ce (diff)
short edge e update
-rw-r--r--poly2.c91
1 files changed, 72 insertions, 19 deletions
diff --git a/poly2.c b/poly2.c
index 0d8632b..cc8e41c 100644
--- a/poly2.c
+++ b/poly2.c
@@ -121,7 +121,6 @@ step_y (sample_t yi)
return yi + 1;
}
-
typedef struct polygon_t polygon_t;
typedef struct point_t point_t;
typedef struct seg_t seg_t;
@@ -154,7 +153,8 @@ typedef struct uninitialized_edge_t uninitialized_edge_t;
typedef enum
{
VERTICAL,
- SHORT,
+ SHORT_W,
+ SHORT_E,
LONG,
UNINITIALIZED
} edge_type_t;
@@ -162,36 +162,39 @@ typedef enum
struct edge_common_t
{
edge_type_t type;
- sample_t bottom;
int dir;
+ sample_t xi;
+ sample_t bottom;
};
struct short_edge_t
{
- sample_t xi;
- uint32_t e;
- uint32_t delta_e_big_x;
- uint32_t delta_e_small_x;
- uint32_t delta_e_big_y;
- uint32_t delta_e_small_y;
+ edge_common_t common;
+ uint32_t e;
+ uint32_t delta_e_big_x;
+ uint32_t delta_e_small_x;
+ uint32_t delta_e_big_y;
+ uint32_t delta_e_small_y;
};
struct vertical_edge_t
{
- sample_t xi;
+ edge_common_t common;
};
struct long_edge_t
{
+ edge_common_t common;
/* stuff here, pointer */
};
struct uninitialized_edge_t
{
- sample_t yi;
- const seg_t *seg;
- const point_t *top;
- const point_t *bottom;
+ edge_common_t common;
+ sample_t yi;
+ const seg_t * seg;
+ const point_t * top;
+ const point_t * bottom;
};
union edge_t
@@ -205,6 +208,48 @@ union edge_t
};
static void
+short_e_edge_update_error (short_edge_t *edge)
+{
+ while (edge->e <= 0)
+ {
+ if (fixed_frac (edge->common.xi) == N_GRID_X - 1)
+ {
+ edge->e += edge->delta_e_big_x;
+ edge->common.xi = fixed_floor (edge->common.xi + fixed_1);
+ }
+ else
+ {
+ edge->e += edge->delta_e_small_x;
+ edge->common.xi++;
+ }
+ }
+}
+
+static void
+short_w_edge_update_error (short_edge_t *edge)
+{
+again:
+ if (fixed_frac (edge->common.xi) == 0)
+ {
+ if (edge->e > edge->delta_e_big_x)
+ {
+ edge->e -= edge->delta_e_big_x;
+ edge->common.xi = (edge->common.xi - fixed_1) | (N_GRID_X - 1);
+ goto again;
+ }
+ }
+ else
+ {
+ if (edge->e > edge->delta_e_small_x)
+ {
+ edge->e -= edge->delta_e_small_x;
+ edge->common.xi--;
+ goto again;
+ }
+ }
+}
+
+static void
edge_init (edge_t *edge, sample_t first_yi)
{
const point_t *top = edge->uninitialized.top;
@@ -213,12 +258,12 @@ edge_init (edge_t *edge, sample_t first_yi)
edge->common.dir = 2 * (top == &seg->p1) - 1;
edge->common.bottom = next_sample_y (bottom->y);
+ edge->common.xi = next_sample_x (top->x);
if (top->x == bottom->x)
{
/* vertical */
edge->common.type = VERTICAL;
- edge->vertical.xi = next_sample_x (top->x);
}
else
{
@@ -234,16 +279,24 @@ edge_init (edge_t *edge, sample_t first_yi)
dx < 8 * dy)
{
/* short */
- sample_t xi = next_sample_x (top->x);
-
- edge->short_.xi = xi;
edge->short_.e =
- (sample_to_pos_x (xi) - top->x) * dy -
+ (sample_to_pos_x (edge->common.xi) - top->x) * dy -
(sample_to_pos_y (first_yi) - top->y) * dx;
edge->short_.delta_e_big_x = BIG_STEP_X * dy;
edge->short_.delta_e_small_x = SMALL_STEP_X * dy;
edge->short_.delta_e_big_y = BIG_STEP_Y * dx;
edge->short_.delta_e_small_y = SMALL_STEP_Y * dx;
+
+ if (dx >= 0)
+ {
+ edge->common.type = SHORT_E;
+ short_e_edge_update_error (&edge->short_);
+ }
+ else
+ {
+ edge->common.type = SHORT_W;
+ short_w_edge_update_error (&edge->short_);
+ }
}
else
{