/*
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 .
Author: Eleni Maria Stea
*/
#include
#include
#include
#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; iwidth * 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; iwidth) >> 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 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;
}