X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fflipscreen3d.c;fp=hacks%2Fglx%2Fflipscreen3d.c;h=c2bca2762f11c0e3e304c8b33785f41d61cbbd11;hb=8eb2873d7054e705c4e83f22d18c40946a9e2529;hp=0000000000000000000000000000000000000000;hpb=a1d41b2aa6e18bf9a49b914a99dda8232c5d7762;p=xscreensaver diff --git a/hacks/glx/flipscreen3d.c b/hacks/glx/flipscreen3d.c new file mode 100644 index 00000000..c2bca276 --- /dev/null +++ b/hacks/glx/flipscreen3d.c @@ -0,0 +1,449 @@ +/* + * screenflip - takes snapshots of the screen and flips it around + * + * version 1.0 - Oct 24, 2001 + * + * Copyright (C) 2001 Ben Buxton (bb@cactii.net) + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#include + + +#ifdef STANDALONE +# define PROGCLASS "Screenflip" +# define HACK_INIT init_screenflip +# define HACK_DRAW draw_screenflip +# define HACK_RESHAPE reshape_screenflip +# define screenflip_opts xlockmore_opts +/* insert defaults here */ + +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*rotate: True \n" \ + +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +/* lifted from lament.c */ +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + + +#ifdef USE_GL + +#include + +int rotate; + +int winw, winh; +int tw, th; /* texture width, height */ +int tx, ty; +GLfloat max_tx, max_ty; + +#define QW 12 +#define QH 12 +GLfloat qw = QW, qh = QH; /* q? are for the quad we'll draw */ +GLfloat qx = -6 , qy = 6; + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static XrmOptionDescRec opts[] = { + {"+rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "false" }, + {"-rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "true" }, +}; + + +static argtype vars[] = { + {(caddr_t *) &rotate, "rotate", "Rotate", "True", t_Bool}, +}; + + + +ModeSpecOpt screenflip_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +#ifdef USE_MODULES +ModStruct screenflip_description = +{"screenflip", "init_screenflip", "draw_screenflip", "release_screenflip", + "draw_screenflip", "init_screenflip", NULL, &screenflip_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Screenflips", 0, NULL}; + +#endif + + +typedef struct { + GLXContext *glx_context; + Window window; +} Screenflip; + +static Screenflip *screenflip = NULL; + +#include +#include +#include +#include +#include "grab-ximage.h" + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + +static GLfloat viewer[] = {0.0, 0.0, 15.0}; + +int regrab = 0; +int fadetime = 0; /* fade before regrab */ + + +/* draw the texture mapped quad (actually two back to back)*/ +void showscreen(int frozen) +{ + static GLfloat r = 1, g = 1, b = 1, a = 1; + GLfloat qxw, qyh; + GLfloat x, y, w, h; + /* static int stretch; */ + static GLfloat stretch_val_x = 0, stretch_val_y = 0; + static GLfloat stretch_val_dx = 0, stretch_val_dy = 0; + /* static int stretch_x = 0, stretch_y = 0; */ + + if (fadetime) { +/* r -= 0.02; g -= 0.02; b -= 0.02; */ + a -= 0.02; + if (a < 0) { + regrab = 1; + fadetime = 0; + } + } else if (a < 0) { + r = g = b = a = 1; + stretch_val_x = stretch_val_y = stretch_val_dx = stretch_val_dy = 0; + } + if (stretch_val_dx == 0 && !frozen && !(random() % 25)) + stretch_val_dx = (float)(random() % 100) / 5000; + if (stretch_val_dy == 0 && !frozen && !(random() % 25)) + stretch_val_dy = (float)(random() % 100) / 5000; + + qxw = qx+qw; + qyh = qy-qh; + x = qx; y = qy; + w = qxw; h = qyh; + + if (!frozen) { + w *= sin (stretch_val_x) + 1; + x *= sin (stretch_val_x) + 1; + if (!fadetime) stretch_val_x += stretch_val_dx; + if (stretch_val_x > 2*M_PI && !(random() % 5)) + stretch_val_dx = (float)(random() % 100) / 5000; + else + stretch_val_x -= 2*M_PI; + + if (!fadetime) stretch_val_y += stretch_val_dy; + h *= sin (stretch_val_y) / 2 + 1; + y *= sin (stretch_val_y) / 2 + 1; + if (stretch_val_y > 2*M_PI && !(random() % 5)) + stretch_val_dy = (float)(random() % 100) / 5000; + else + stretch_val_y -= 2*M_PI; + } + + glColor4f(r, g, b, a); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); + + glBegin(GL_QUADS); + + glNormal3f(0, 0, 1); + + glTexCoord2f(0, max_ty); + glVertex3f(x, y, 0); + + glTexCoord2f(max_tx, max_ty); + glVertex3f(w, y, 0); + + glTexCoord2f(max_tx, 0); + glVertex3f(w, h, 0); + + glTexCoord2f(0, 0); + glVertex3f(x, h, 0); + + glNormal3f(0, 0, -1); + + glTexCoord2f(0, max_ty); + glVertex3f(x, y, -0.05); + + glTexCoord2f(0, 0); + glVertex3f(x, h, -0.05); + + glTexCoord2f(max_tx, 0); + glVertex3f(w, h, -0.05); + + glTexCoord2f(max_tx, max_ty); + glVertex3f(w, y, -0.05); + + glEnd(); + + + glDisable(GL_TEXTURE_2D); + glDepthMask(GL_TRUE); + + glBegin(GL_LINE_LOOP); + glVertex3f(x, y, 0); + glVertex3f(x, h, 0); + glVertex3f(w, h, 0); + glVertex3f(w, y, 0); + glEnd(); + glDisable(GL_BLEND); + +} + +/* This function is responsible for 'zooming back' the square after + * a new chunk has been grabbed with getSnapshot(), and positioning + * it suitably on the screen. Once positioned (where we begin to rotate), + * it just does a glTranslatef() and returns 1 + */ + +int inposition(void) +{ + static GLfloat curx, cury, curz = 0; + GLfloat wx; + GLfloat wy; + wx = 0 - (qw/2); + wy = (qh/2); + + if (curx == 0) curx = qx; + if (cury == 0) cury = qy; + if (regrab) { + curz = 0; + curx = qx; + cury = qy; + regrab = 0; + } + if (curz > -10 || curx > wx + 0.1 || curx < wx - 0.1 || + cury > wy + 0.1 || cury < wy - 0.1) { + if (curz > -10) + curz -= 0.05; + if (curx > wx) { + qx -= 0.02; + curx -= 0.02; + } + if (curx < wx) { + qx += 0.02; + curx += 0.02; + } + if (cury > wy) { + qy -= 0.02; + cury -= 0.02; + } + if (cury < wy) { + qy += 0.02; + cury += 0.02; + } + glTranslatef(0, 0, curz); + return 0; + } + glTranslatef(0, 0, curz); + return 1; + +} + +void drawgrid(void) +{ + int i; + + glColor3f(0, 0.7, 0); + glBegin(GL_LINES); + for (i = 0 ; i <= 50; i+=2) { + glVertex3f( -25, -15, i-70); + glVertex3f( 25, -15, i-70); + glVertex3f( i-25, -15, -70); + glVertex3f( i-25, -15, -20); + } + glEnd(); +} + +void display(void) +{ + static GLfloat rx=1, ry=1, rz=0; + static GLfloat rot = 0; + static GLfloat drot = 0; + static GLfloat odrot = 1; + static GLfloat ddrot = 0; + static float theta = 0, rho = 0, dtheta = 0, drho = 0, gamma = 0, dgamma = 0; + static GLfloat orot; + int frozen; + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + glPushMatrix(); + + if (inposition()) { + frozen = 0; + glTranslatef(5 * sin(theta), 5 * sin(rho), 10 * cos(gamma) - 10); +/* randomly change the speed */ + if (!(random() % 300)) { + if (random() % 2) + drho = 1/60 - (float)(random() % 100)/3000; + if (random() % 2) + dtheta = 1/60 - (float)(random() % 100)/3000; + if (random() % 2) + dgamma = 1/60 - (float)(random() % 100)/3000; + } + if (rotate) glRotatef(rot, rx, ry, rz); +/* update variables with each frame */ + if (!fadetime) { + theta += dtheta; + rho += drho; + gamma += dgamma; + rot += drot; + drot += ddrot; + } +/* dont let our rotation speed get too high */ + if (drot > 5 && ddrot > 0) + ddrot = 0 - (GLfloat)(random() % 100) / 1000; + else if (drot < -5 && ddrot < 0) + ddrot = (GLfloat)(random() % 100) / 1000; + } else { /* reset some paramaters */ + ddrot = 0.05 - (GLfloat)(random() % 100) / 1000; + theta = rho = gamma = 0; + rot = 0; + frozen = 1; + } + if (!fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate change */ + rx = (GLfloat)(random() % 100) / 100; + ry = (GLfloat)(random() % 100) / 100; + rz = (GLfloat)(random() % 100) / 100; + } + if (odrot * drot < 0 && tw < winw && !(random() % 10)) { + fadetime = 1; /* randomly fade and get new snapshot */ + } + orot = rot; + odrot = drot; + if (rot > 360 || rot < -360) /* dont overflow rotation! */ + rot -= rot; + showscreen(frozen); + glPopMatrix(); + glFlush(); +} + +void reshape_screenflip(ModeInfo *mi, int width, int height) +{ + glViewport(0,0,(GLint)width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1, 2.0, 85); + glMatrixMode(GL_MODELVIEW); + winw = width; + winh = height; +} + +void getSnapshot (ModeInfo *modeinfo) +{ + XImage *ximage; + + ximage = screen_to_ximage (modeinfo->xgwa.screen, modeinfo->window); + + qw = QW; qh = QH; + tw = modeinfo->xgwa.width; + th = modeinfo->xgwa.height; + + qx += (qw*tw/winw); + qy -= (qh*th/winh); + + qw *= (GLfloat)tw/winw; + qh *= (GLfloat)th/winh; + + max_tx = (GLfloat) tw / (GLfloat) ximage->width; + max_ty = (GLfloat) th / (GLfloat) ximage->height; + + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + if (gluBuild2DMipmaps(GL_TEXTURE_2D, 3, + ximage->width, ximage->height, + GL_RGBA, GL_UNSIGNED_BYTE, ximage->data)) { + printf("Error!\n"); + exit(1); + } + free(ximage->data); + ximage->data = 0; + XDestroyImage (ximage); +} + +void init_screenflip(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + Screenflip *c; + + if (screenflip == NULL) { + if ((screenflip = (Screenflip *) calloc(MI_NUM_SCREENS(mi), + sizeof(Screenflip))) == NULL) + return; + } + c = &screenflip[screen]; + c->window = MI_WINDOW(mi); + + if ((c->glx_context = init_GL(mi)) != NULL) { + reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + winh = MI_WIN_HEIGHT(mi); + winw = MI_WIN_WIDTH(mi); + glClearColor(0.0,0.0,0.0,0.0); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + glDisable(GL_LIGHTING); + + getSnapshot(mi); +} + +void draw_screenflip(ModeInfo *mi) +{ + Screenflip *c = &screenflip[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if (!c->glx_context) + return; + + glXMakeCurrent(disp, w, *(c->glx_context)); + + if (regrab) + getSnapshot(mi); + + display(); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +void release_screenflip(ModeInfo *mi) +{ + if (screenflip != NULL) { + (void) free((void *) screenflip); + screenflip = NULL; + } + FreeAllGL(MI); +} + +#endif