summaryrefslogtreecommitdiff
path: root/tunnel/src/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tunnel/src/main.cc')
-rw-r--r--tunnel/src/main.cc182
1 files changed, 182 insertions, 0 deletions
diff --git a/tunnel/src/main.cc b/tunnel/src/main.cc
new file mode 100644
index 0000000..c050c8c
--- /dev/null
+++ b/tunnel/src/main.cc
@@ -0,0 +1,182 @@
+/*
+winnie - an experimental window system
+
+Copyright (C) 2013 Eleni Maria Stea
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Author: Eleni Maria Stea <elene.mst@gmail.com>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "winnie.h"
+#include "tunneltex.h"
+
+static void resize(int xsz, int ysz);
+static void display(Window *win);
+static void timer(Window *win);
+static bool calc_tunnel_mapping();
+
+static int xsz = 512;
+static int ysz = 384;
+
+static Pixmap *tex;
+static float *umap, *vmap;
+static unsigned long start_time;
+
+extern "C" bool init()
+{
+ Window *win = new Window;
+ win->set_title("tunnel effect");
+ win->move(380, 280);
+ win->resize(xsz, ysz);
+ win->set_display_callback(display);
+ win->set_timer_callback(timer);
+
+ tex = new Pixmap;
+ tex->set_image(gimp_image.width, gimp_image.height);
+
+ for(int i=0; i<tex->width * tex->height; i++) {
+ tex->pixels[i * 4] = gimp_image.pixel_data[i * 3];
+ tex->pixels[i * 4 + 1] = gimp_image.pixel_data[i * 3 + 1];
+ tex->pixels[i * 4 + 2] = gimp_image.pixel_data[i * 3 + 2];
+ }
+
+ resize(xsz, ysz);
+ wm->add_window(win);
+
+ start_time = winnie_get_time();
+ set_window_timer(win, 25, TIMER_REPEAT);
+ return true;
+}
+
+extern "C" void cleanup()
+{
+ delete tex;
+}
+
+static void resize(int width, int height)
+{
+ xsz = width;
+ ysz = height;
+
+ calc_tunnel_mapping();
+}
+
+static void display(Window *win)
+{
+ Pixmap *fb = get_framebuffer_pixmap();
+ Rect wrect = win->get_absolute_rect();
+
+ if(wrect.width != xsz || wrect.height != ysz) {
+ resize(wrect.width, wrect.height);
+ }
+
+ unsigned long msec = winnie_get_time() - start_time;
+ float sec = (float)msec / 1000.0f;
+
+ float uoffs = sec * 0.75;
+ float voffs = sec;
+
+ unsigned char *fbptr = fb->pixels + (wrect.y * fb->width + wrect.x) * 4;
+ float *uptr = umap;
+ float *vptr = vmap;
+
+ for(int i=0; i<ysz; i++) {
+ for(int j=0; j<xsz; j++) {
+ float u = *uptr++ * 8.0f;
+ float v = *vptr++;
+ //unsigned long tx = ((((unsigned long)((u << 3) - uoffs)) & 0xff) * tex->width) >> 8;
+ //unsigned long tx = ((((u << 3) * tex->width) >> 8) + uoffs) % tex->width;
+ //unsigned long ty = (((unsigned long)(v + voffs * 2) & 0xff) * tex->height) >> 8;
+ int tx = fmod(u - uoffs, 1.0f) * tex->width;
+ if(tx < 0) {
+ tx += tex->width;
+ }
+ int ty = fmod(v + voffs, 1.0f) * tex->height;
+
+ float fog = 1.0f - v / 8.0f;
+ if(fog < 0.0f) fog = 0.0f;
+ if(fog > 1.0f) fog = 1.0f;
+
+ unsigned char red, green, blue;
+ if(i == ysz / 2 && j == xsz / 2) {
+ red = green = blue = 0;
+ } else {
+ int offs = (ty * tex->width + tx) * 4;
+ red = tex->pixels[offs];
+ green = tex->pixels[offs + 1];
+ blue = tex->pixels[offs + 2];
+ }
+
+ red = red * fog;
+ green = green * fog;
+ blue = blue * fog;
+
+ fbptr[j * 4] = red;
+ fbptr[j * 4 + 1] = green;
+ fbptr[j * 4 + 2] = blue;
+ }
+ fbptr += fb->width * 4;
+ }
+}
+
+static void timer(Window *win)
+{
+ wm->invalidate_region(win->get_absolute_rect());
+}
+
+static bool calc_tunnel_mapping()
+{
+ int i, j;
+ float *uptr, *vptr;
+
+ if(umap || vmap) {
+ free(umap);
+ free(vmap);
+ }
+
+ if(!(umap = (float*)malloc(xsz * ysz * sizeof *umap))) {
+ return false;
+ }
+ if(!(vmap = (float*)malloc(xsz * ysz * sizeof *umap))) {
+ free(umap);
+ return false;
+ }
+
+ uptr = umap;
+ vptr = vmap;
+
+ for(i=0; i<ysz; i++) {
+ for(j=0; j<xsz; j++) {
+ float x = ((float)j / xsz * 2.0 - 1.0) * 1.33333;
+ float y = (float)i / ysz * 2.0 - 1.0;
+ float angle, z, dist;
+
+ if(fabs(x) > 0.00001) {
+ angle = atan2(y, x) + M_PI;
+ } else {
+ angle = y < 0.0 ? M_PI / 2.0 : 3.0 * M_PI / 2.0;
+ }
+ dist = sqrt(x * x + y * y);
+ z = 2.0 / dist;
+
+ *uptr++ = angle * 0.5 / M_PI;
+ *vptr++ = z;
+ }
+ }
+ return true;
+}