diff options
Diffstat (limited to 'src/engine/3dd.c')
-rw-r--r-- | src/engine/3dd.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/engine/3dd.c b/src/engine/3dd.c new file mode 100644 index 0000000..f6a92fb --- /dev/null +++ b/src/engine/3dd.c @@ -0,0 +1,200 @@ +#ifndef UNSUPPORTED +static void convert_3d(struct filter *f, int *x1, int *y1) +{ + struct threeddata *data = (struct threeddata *) f->data; + int y; + int x = *x1; + unsigned int inp; + unsigned int height = data->height; + register CONST spixel_t *input; + if (x >= f->childimage->width - 5 || x < 0 + || *y1 > f->childimage->height) { + *x1 += *y1 / 2; + return; + } + if (x < 0) + x = 0; + for (y = f->childimage->height - 3; y >= 0; y--) { + int d; + input = ((spixel_t *) f->childimage->currlines[y] + y / 2); + inp = (input[x] + input[x + 1] + input[x + 2] + + input[x + 3] + input[x + 4] + input[x + 5]); + input = ((spixel_t *) f->childimage->currlines[y + 1] + y / 2); + inp += (input[x] + input[x + 1] + input[x + 2] + + input[x + 3] + input[x + 4] + input[x + 5]); + input = ((spixel_t *) f->childimage->currlines[y + 2] + y / 2); + inp += (input[x] + input[x + 1] + input[x + 2] + + input[x + 3] + input[x + 4] + input[x + 5]); + d = y - (inp / 16 > height ? height : inp / 16); + if (d <= *y1) { + *y1 = y; + *x1 = x + y / 2; + return; + } + } + *x1 += *y1 / 2; + return; +} + +static void convertup_3d(struct filter *f, int *x1, int *y1) +{ + struct threeddata *data = (struct threeddata *) f->data; + int y = *y1; + int x = *x1; + unsigned int inp; + unsigned int height = data->height; + register CONST spixel_t *input; + if (x >= f->childimage->width - 5) + x = f->childimage->width - 6; + if (y >= f->childimage->height - 3) + y = f->childimage->height - 3; + if (x < 0) + x = 0; + if (y < 0) + y = 0; + input = ((spixel_t *) f->childimage->currlines[y] + y / 2); + inp = (input[x] + input[x + 1] + input[x + 2] + + input[x + 3] + input[x + 4] + input[x + 5]); + input = ((spixel_t *) f->childimage->currlines[y + 1] + y / 2); + inp += (input[x] + input[x + 1] + input[x + 2] + + input[x + 3] + input[x + 4] + input[x + 5]); + input = ((spixel_t *) f->childimage->currlines[y + 2] + y / 2); + inp += (input[x] + input[x + 1] + input[x + 2] + + input[x + 3] + input[x + 4] + input[x + 5]); + *x1 -= *y1 / 2; + *y1 = y - (inp / 16 > height ? height : inp / 16); +} + +static void do_3d(void *dataptr, struct taskinfo *task, int r1, int r2) +{ + struct filter *RESTRICT f = (struct filter *) dataptr; + unsigned int y; + int maxinp = 0; + unsigned int x; + unsigned int end; + unsigned int sum; + spixel_t CONST *RESTRICT input; + unsigned int *RESTRICT lengths; + unsigned int *RESTRICT sums; + unsigned int *RESTRICT relsums; + struct threeddata *data = (struct threeddata *) f->data; + + + /* Copy to local variables to improve cse and memory references. */ + unsigned int height = data->height; + unsigned int stereogrammode = data->stereogrammode; + unsigned int colheight = data->colheight; + unsigned int midcolor = data->midcolor; + unsigned int darkcolor = data->darkcolor; + CONST unsigned int *RESTRICT pixels = data->pixels; + cpixel_t *RESTRICT * RESTRICT currlines = + (cpixel_t * RESTRICT * RESTRICT) f->image->currlines; + struct inp { + int max; + unsigned int down; + } *inpdata; + +#ifdef HAVE_ALLOCA1 + lengths = + (unsigned int *) alloca(sizeof(unsigned int) * f->image->width); + inpdata = + (struct inp *) alloca(sizeof(struct inp) * (f->image->width + 2)); + sums = + (unsigned int *) alloca(sizeof(unsigned int) * + (f->image->width + 2) * 2); +#else + lengths = + (unsigned int *) malloc(sizeof(unsigned int) * f->image->width); + inpdata = + (struct inp *) malloc(sizeof(struct inp) * (f->image->width + 2)); + sums = + (unsigned int *) malloc(sizeof(unsigned int) * + (f->image->width + 2) * 2); +#endif + for (x = 0; x < (unsigned int) f->image->width; x++) + lengths[x] = f->image->height - 1, + sums[x * 2 + 0] = 0, sums[x * 2 + 1] = 0, inpdata[x].max = 0; + sums[x * 2 + 0] = 0, sums[x * 2 + 1] = 0, inpdata[x].max = 0; + inpdata[x + 1].max = 0; + end = r2; + for (y = f->childimage->height - 2; y > 0;) { + y--; + input = ((spixel_t *) f->childimage->currlines[y] + y / 2); + x = r1; + relsums = sums + (y & 1); + + /* Fix boundary cases. */ + /*relsums[0] = relsums[1]; + relsums[end*2-1] = relsums[end*2-2]; */ + inpdata[end + 1] = inpdata[end] = inpdata[end - 1]; + sum = + input[x] + input[x + 1] + input[x + 2] + input[x + 3] + + input[x + 4] + input[x + 5]; + + while (x < end) { + unsigned int inp; + unsigned int d; + + /* Average pixel values of 5*3 square to get nicer shapes. */ + sum += input[x + 6] - input[x]; + inp = sum + sums[x * 2 + 1] + sums[x * 2]; + relsums[x * 2] = sum; + inpdata[x].down = inp; + + /* Calculate shades. */ + maxinp = inpdata[x + 2].max; + if ((int) inp > maxinp) + inpdata[x].max = inp - 32; + else + inpdata[x].max = maxinp - 32; + + /* caluclate top of mountain. */ + d = inp / 16; + d = y - (d > height ? height : d); + + /* Underflow */ + if (d > 65535U) + d = 0; + if (d < lengths[x]) { + int y1; + unsigned int color; + if (stereogrammode) + color = pixels[y]; + else if (inp / 16 > height) + /*Red thinks on the top. */ + color = + pixels[inp / 16 >= + colheight ? colheight : inp / 16]; + else { + int c; + /* Simple shading model. + Depends only on the preceding voxel. */ + + c = ((int) inpdata[x + 2].down - (int) inp) / 8; + + /* Get shades. */ + color = + ((int) inp > maxinp ? midcolor : darkcolor) - c; + color = + pixels[color < + 65535 ? (color < + height ? color : height) : 0]; + } + for (y1 = lengths[x]; y1 >= (int) d; y1--) { + p_setp(currlines[y1], x, color); + } + lengths[x] = d; + } + x++; + } + } +#ifndef HAVE_ALLOCA1 + free(lengths); + free(inpdata); + free(sums); +#endif +} +#endif +#undef do_3d +#undef convert_3d +#undef convertup_3d |