Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/engine/3dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/3dd.c')
-rw-r--r--src/engine/3dd.c200
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