summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@l3000.localdomain>2010-12-13 12:28:47 -0500
committerSøren Sandmann Pedersen <ssp@l3000.localdomain>2010-12-20 10:48:52 -0500
commit47121d21057f95585f7353109f15b55bcab896d0 (patch)
tree0f5b218a32e76feb5be7e37727b19fb4b139e51a
parent634415aceeb0e296abe5990bbf79f2c5fb342494 (diff)
sample_t type
-rw-r--r--dda.c140
1 files changed, 70 insertions, 70 deletions
diff --git a/dda.c b/dda.c
index 796b08d..fa74365 100644
--- a/dda.c
+++ b/dda.c
@@ -49,72 +49,69 @@ typedef int32_t fixed_t;
#define SMALL_STEP_X STEP_X_SMALL(8)
#define FIRST_STEP_X X_FRAC_FIRST(8)
+/* A sample_t is a fixed_t where the fractional bits are replaced with
+ * a small integer indicating the sample number in the pixel.
+ */
+typedef int32_t sample_t;
+
static fixed_t
-sample_to_pos_x (int x)
+sample_to_pos_x (sample_t x)
{
- return (x & 0xffffff00) + (x & 0xff) * SMALL_STEP_X + FIRST_STEP_X;
+ return fixed_floor (x) + FIRST_STEP_X + fixed_frac (x) * SMALL_STEP_X;
}
static fixed_t
-sample_to_pos_y (int y)
+sample_to_pos_y (sample_t y)
{
- return (y & 0xffffff00) + (y & 0xff) * SMALL_STEP_Y + FIRST_STEP_Y;
+ return fixed_floor (y) + FIRST_STEP_Y + fixed_frac (y) * SMALL_STEP_Y;
}
-static int
+static sample_t
next_sample_y (fixed_t y)
{
fixed_t f = fixed_frac (y);
- fixed_t i = fixed_to_int (y);
- int sno;
+ fixed_t i = fixed_floor (y);
+ uint32_t sample_no;
- sno = ((f - FIRST_STEP_Y + SMALL_STEP_Y - fixed_e) / SMALL_STEP_Y);
+ sample_no = ((f - FIRST_STEP_Y + SMALL_STEP_Y - fixed_e) / SMALL_STEP_Y);
- if (sno >= N_GRID_Y)
+ if (sample_no >= N_GRID_Y)
{
- if (i == fixed_max_int)
- {
- sno = N_GRID_Y - 1; /* saturate */
- }
- else
- {
- sno -= (N_GRID_Y + 1);
- i++;
- }
+ /* FIXME: i can overflow here, but we should probably just
+ * reject edges that close to the border
+ */
+ sample_no -= (N_GRID_Y + 1);
+ i += fixed_1;
}
- return (i << 8) | sno;
+ return i + sample_no;
}
-static int
+static sample_t
next_sample_x (fixed_t x)
{
fixed_t f = fixed_frac (x);
- fixed_t i = fixed_to_int (x);
- int sno;
+ fixed_t i = fixed_floor (x);
+ int sample_no;
- sno = ((f - FIRST_STEP_X + SMALL_STEP_X - fixed_e) / SMALL_STEP_X);
+ sample_no = ((f - FIRST_STEP_X + SMALL_STEP_X - fixed_e) / SMALL_STEP_X);
- if (sno >= N_GRID_X)
+ if (sample_no >= N_GRID_X)
{
- if (i == fixed_max_int)
- {
- sno = N_GRID_X - 1; /* saturate */
- }
- else
- {
- sno -= (N_GRID_X + 1);
- i++;
- }
+ /* FIXME: i can overflow here, but we should probably just
+ * reject edges that close to the border
+ */
+ sample_no -= (N_GRID_X + 1);
+ i += fixed_1;
}
- return (i << 8) | sno;
+ return i + sample_no;
}
typedef struct
{
- int xi;
- int bottom;
+ sample_t xi;
+ sample_t bottom;
int64_t e;
int64_t delta_e_big_x;
int64_t delta_e_small_x;
@@ -140,25 +137,30 @@ edge_init (edge_t *edge, fixed_t x0, fixed_t y0, fixed_t x1, fixed_t y1)
edge->delta_e_small_y = SMALL_STEP_Y * dx;
}
+typedef void (* emitter_t) (sample_t x, sample_t y, void *data);
+
/* FIXME:
*
* When updating the xi, we are stepping one sample at a time, but we
* can do better because we know how the minimum damage that is done on every Y
* step. This means we know we have to undo at least that much damage, so
* we can step much more than one sample if the edge is close to horizontal.
+ *
+ * The first micro-step is an exception - it may not do as much damage as
+ * normal.
*/
static void
-edge_step (edge_t *edge, test_data_t *testdata, int i, int *yi)
+edge_step (edge_t *edge, int *yi, emitter_t emit, void *data)
{
if (edge->delta_e_small_y >= 0)
{
while (edge->e <= 0)
{
- if ((edge->xi & 0xff) == N_GRID_X - 1)
+ if (fixed_frac (edge->xi) == N_GRID_X - 1)
{
edge->e += edge->delta_e_big_x;
- edge->xi += (1 << 8);
- edge->xi &= 0xffffff00;
+ edge->xi += fixed_1;
+ edge->xi = fixed_floor (edge->xi);
}
else
{
@@ -170,12 +172,12 @@ edge_step (edge_t *edge, test_data_t *testdata, int i, int *yi)
else
{
begin:
- if ((edge->xi & 0xff) == 0)
+ if (fixed_frac (edge->xi) == 0)
{
if (edge->e > edge->delta_e_big_x)
{
edge->e -= edge->delta_e_big_x;
- edge->xi -= (1 << 8);
+ edge->xi -= fixed_1;
edge->xi |= (N_GRID_X - 1);
goto small;
}
@@ -192,32 +194,13 @@ edge_step (edge_t *edge, test_data_t *testdata, int i, int *yi)
}
}
-#if 0
- printf ("Pos: %f %f\n",
- fixed_to_double (sample_to_pos_x (edge->xi)),
- fixed_to_double (sample_to_pos_y (*yi)));
-#endif
- printf ("Pos: %x %x\n", edge->xi, *yi);
-#if 0
- fixed_to_double (sample_to_pos_x (edge->xi)),
- fixed_to_double (sample_to_pos_y (*yi)));
-#endif
-
-#if 0
- if (testdata->points[i++] != sample_to_pos (edge->xi) ||
- testdata->points[i++] != sample_to_pos (*yi))
- {
- printf ("%d error %f %f\n", i, testdata->points[i - 1],
- sample_to_pos (edge->xi));
- exit (-1);
- }
-#endif
+ emit (edge->xi, *yi, data);
- if (((*yi) & 0xff) == (N_GRID_Y - 1))
+ if (fixed_frac (*yi) == N_GRID_Y - 1)
{
edge->e -= edge->delta_e_big_y;
- (*yi) += (1 << 8);
- (*yi) &= 0xffffff00;
+ (*yi) += fixed_1;
+ (*yi) = fixed_floor (*yi);
}
else
{
@@ -227,6 +210,19 @@ edge_step (edge_t *edge, test_data_t *testdata, int i, int *yi)
}
static void
+emit (sample_t xi, sample_t yi, void *data)
+{
+ double *points = data;
+
+ printf ("sample %x %x (%f %f)\n",
+ xi, yi,
+ fixed_to_double (sample_to_pos_x (xi)),
+ fixed_to_double (sample_to_pos_y (yi)));
+
+ return;
+}
+
+static void
dda (test_data_t *testdata)
{
fixed_t x0 = double_to_fixed (testdata->segment.x0);
@@ -234,13 +230,11 @@ dda (test_data_t *testdata)
fixed_t x1 = double_to_fixed (testdata->segment.x1);
fixed_t y1 = double_to_fixed (testdata->segment.y1);
-#if 0
- printf ("= = = = %f %f %f %f = = = = \n",
+ printf ("f = = = %f %f %f %f = = = = \n",
fixed_to_double (x0),
fixed_to_double (y0),
fixed_to_double (x1),
fixed_to_double (y1));
-#endif
edge_t edge;
int i = 0;
@@ -251,16 +245,22 @@ dda (test_data_t *testdata)
yi = next_sample_y (y0);
while (yi < edge.bottom)
{
- edge_step (&edge, testdata, i, &yi);
+ edge_step (&edge, &yi, emit, &(testdata->points[i]));
i += 2;
}
}
+test_data_t td = { { 0.52, -23, 3.5, 10.733 } };
+
int
main ()
{
- test_data_t td = { { 0.5, 0.5, 3.5, 10.733 } };
+ printf (". = = = %f %f %f %f = = = = \n",
+ td.segment.x0,
+ td.segment.y0,
+ td.segment.x1,
+ td.segment.y1);
dda (&td);