2
* flipscreen3d - takes snapshots of the screen and flips it around
4
* version 1.0 - Oct 24, 2001
6
* Copyright (C) 2001 Ben Buxton (bb@cactii.net)
8
* Permission to use, copy, modify, distribute, and sell this software and its
9
* documentation for any purpose is hereby granted without fee, provided that
10
* the above copyright notice appear in all copies and that both that
11
* copyright notice and this permission notice appear in supporting
12
* documentation. No representations are made about the suitability of this
13
* software for any purpose. It is provided "as is" without express or
17
#include <X11/Intrinsic.h>
21
# define PROGCLASS "FlipScreen3D"
22
# define HACK_INIT init_screenflip
23
# define HACK_DRAW draw_screenflip
24
# define HACK_RESHAPE reshape_screenflip
25
# define HACK_HANDLE_EVENT screenflip_handle_event
26
# define EVENT_MASK PointerMotionMask
27
# define screenflip_opts xlockmore_opts
28
/* insert defaults here */
30
#define DEFAULTS "*delay: 20000 \n" \
31
"*showFPS: False \n" \
32
"*wireframe: False \n" \
35
# include "xlockmore.h" /* from the xscreensaver distribution */
36
#else /* !STANDALONE */
37
# include "xlock.h" /* from the xlockmore distribution */
38
#endif /* !STANDALONE */
40
/* lifted from lament.c */
41
#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
42
#define RANDSIGN() ((random() & 1) ? 1 : -1)
52
int tw, th; /* texture width, height */
54
GLfloat min_tx, min_ty;
55
GLfloat max_tx, max_ty;
59
GLfloat qw = QW, qh = QH; /* q? are for the quad we'll draw */
60
GLfloat qx = -6 , qy = 6;
63
#define countof(x) (sizeof((x))/sizeof((*x)))
66
static XrmOptionDescRec opts[] = {
67
{"+rotate", ".screenflip.rotate", XrmoptionNoArg, "false" },
68
{"-rotate", ".screenflip.rotate", XrmoptionNoArg, "true" },
72
static argtype vars[] = {
73
{&rotate, "rotate", "Rotate", "True", t_Bool},
78
ModeSpecOpt screenflip_opts = {countof(opts), opts, countof(vars), vars, NULL};
82
ModStruct screenflip_description =
83
{"screenflip", "init_screenflip", "draw_screenflip", "release_screenflip",
84
"draw_screenflip", "init_screenflip", NULL, &screenflip_opts,
85
1000, 1, 2, 1, 4, 1.0, "",
86
"Screenflips", 0, NULL};
92
GLXContext *glx_context;
96
static Screenflip *screenflip = NULL;
102
#include "grab-ximage.h"
103
#include "gltrackball.h"
106
#define M_PI 3.14159265
109
static GLfloat viewer[] = {0.0, 0.0, 15.0};
112
int fadetime = 0; /* fade before regrab */
114
static trackball_state *trackball;
115
static Bool button_down_p = False;
119
screenflip_handle_event (ModeInfo *mi, XEvent *event)
121
if (event->xany.type == ButtonPress &&
122
event->xbutton.button == Button1)
124
button_down_p = True;
125
gltrackball_start (trackball,
126
event->xbutton.x, event->xbutton.y,
127
MI_WIDTH (mi), MI_HEIGHT (mi));
130
else if (event->xany.type == ButtonRelease &&
131
event->xbutton.button == Button1)
133
button_down_p = False;
136
else if (event->xany.type == ButtonPress &&
137
(event->xbutton.button == Button4 ||
138
event->xbutton.button == Button5))
140
gltrackball_mousewheel (trackball, event->xbutton.button, 10,
141
!!event->xbutton.state);
144
else if (event->xany.type == MotionNotify &&
147
gltrackball_track (trackball,
148
event->xmotion.x, event->xmotion.y,
149
MI_WIDTH (mi), MI_HEIGHT (mi));
157
/* draw the texture mapped quad (actually two back to back)*/
158
void showscreen(int frozen, int wire)
160
static GLfloat r = 1, g = 1, b = 1, a = 1;
162
/* static int stretch; */
163
static GLfloat stretch_val_x = 0, stretch_val_y = 0;
164
static GLfloat stretch_val_dx = 0, stretch_val_dy = 0;
165
/* static int stretch_x = 0, stretch_y = 0; */
168
/* r -= 0.02; g -= 0.02; b -= 0.02; */
176
stretch_val_x = stretch_val_y = stretch_val_dx = stretch_val_dy = 0;
178
if (stretch_val_dx == 0 && !frozen && !(random() % 25))
179
stretch_val_dx = (float)(random() % 100) / 5000;
180
if (stretch_val_dy == 0 && !frozen && !(random() % 25))
181
stretch_val_dy = (float)(random() % 100) / 5000;
189
w *= sin (stretch_val_x) + 1;
190
x *= sin (stretch_val_x) + 1;
191
if (!button_down_p) {
192
if (!fadetime) stretch_val_x += stretch_val_dx;
193
if (stretch_val_x > 2*M_PI && !(random() % 5))
194
stretch_val_dx = (float)(random() % 100) / 5000;
196
stretch_val_x -= 2*M_PI;
199
if (!button_down_p && !fadetime) stretch_val_y += stretch_val_dy;
200
h *= sin (stretch_val_y) / 2 + 1;
201
y *= sin (stretch_val_y) / 2 + 1;
202
if (!button_down_p) {
203
if (stretch_val_y > 2*M_PI && !(random() % 5))
204
stretch_val_dy = (float)(random() % 100) / 5000;
206
stretch_val_y -= 2*M_PI;
210
glColor4f(r, g, b, a);
214
glEnable(GL_TEXTURE_2D);
216
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
217
glDepthMask(GL_FALSE);
220
glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
223
glTexCoord2f(max_tx, max_ty); glVertex3f(w, h, 0);
224
glTexCoord2f(max_tx, min_ty); glVertex3f(w, y, 0);
225
glTexCoord2f(min_tx, min_ty); glVertex3f(x, y, 0);
226
glTexCoord2f(min_tx, max_ty); glVertex3f(x, h, 0);
228
glNormal3f(0, 0, -1);
229
glTexCoord2f(min_tx, min_ty); glVertex3f(x, y, -0.05);
230
glTexCoord2f(max_tx, min_ty); glVertex3f(w, y, -0.05);
231
glTexCoord2f(max_tx, max_ty); glVertex3f(w, h, -0.05);
232
glTexCoord2f(min_tx, max_ty); glVertex3f(x, h, -0.05);
236
glDisable(GL_TEXTURE_2D);
237
glDepthMask(GL_TRUE);
239
glBegin(GL_LINE_LOOP);
249
/* This function is responsible for 'zooming back' the square after
250
* a new chunk has been grabbed with getSnapshot(), and positioning
251
* it suitably on the screen. Once positioned (where we begin to rotate),
252
* it just does a glTranslatef() and returns 1
257
static GLfloat curx, cury, curz = 0;
263
if (curx == 0) curx = qx;
264
if (cury == 0) cury = qy;
271
if (curz > -10 || curx > wx + 0.1 || curx < wx - 0.1 ||
272
cury > wy + 0.1 || cury < wy - 0.1) {
291
glTranslatef(0, 0, curz);
294
glTranslatef(0, 0, curz);
303
glColor3f(0, 0.7, 0);
305
for (i = 0 ; i <= 50; i+=2) {
306
glVertex3f( -25, -15, i-70);
307
glVertex3f( 25, -15, i-70);
308
glVertex3f( i-25, -15, -70);
309
glVertex3f( i-25, -15, -20);
314
void display(int wire)
316
static GLfloat rx=1, ry=1, rz=0;
317
static GLfloat rot = 0;
318
static GLfloat drot = 0;
319
static GLfloat odrot = 1;
320
static GLfloat ddrot = 0;
321
static float theta = 0, rho = 0, dtheta = 0, drho = 0, gamma = 0, dgamma = 0;
325
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
327
gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
332
glTranslatef(5 * sin(theta), 5 * sin(rho), 10 * cos(gamma) - 10);
333
/* randomly change the speed */
334
if (!button_down_p && !(random() % 300)) {
336
drho = 1/60 - (float)(random() % 100)/3000;
338
dtheta = 1/60 - (float)(random() % 100)/3000;
340
dgamma = 1/60 - (float)(random() % 100)/3000;
342
gltrackball_rotate (trackball);
343
if (rotate) glRotatef(rot, rx, ry, rz);
344
/* update variables with each frame */
345
if(!button_down_p && !fadetime) {
352
/* dont let our rotation speed get too high */
353
if (drot > 5 && ddrot > 0)
354
ddrot = 0 - (GLfloat)(random() % 100) / 1000;
355
else if (drot < -5 && ddrot < 0)
356
ddrot = (GLfloat)(random() % 100) / 1000;
357
} else { /* reset some paramaters */
358
ddrot = 0.05 - (GLfloat)(random() % 100) / 1000;
359
theta = rho = gamma = 0;
363
if (!button_down_p && !fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate change */
364
rx = (GLfloat)(random() % 100) / 100;
365
ry = (GLfloat)(random() % 100) / 100;
366
rz = (GLfloat)(random() % 100) / 100;
368
if (odrot * drot < 0 && tw < winw && !(random() % 10)) {
369
fadetime = 1; /* randomly fade and get new snapshot */
373
if (rot > 360 || rot < -360) /* dont overflow rotation! */
375
showscreen(frozen, wire);
380
void reshape_screenflip(ModeInfo *mi, int width, int height)
382
glViewport(0,0,(GLint)width, (GLint) height);
383
glMatrixMode(GL_PROJECTION);
385
gluPerspective(45, 1, 2.0, 85);
386
glMatrixMode(GL_MODELVIEW);
391
void getSnapshot (ModeInfo *modeinfo)
393
Bool mipmap_p = True;
397
if (MI_IS_WIREFRAME(modeinfo))
400
if (! screen_to_texture (modeinfo->xgwa.screen, modeinfo->window, 0, 0,
401
mipmap_p, NULL, &geom, &iw, &ih, &tw, &th))
404
min_tx = (GLfloat) geom.x / tw;
405
min_ty = (GLfloat) geom.y / th;
406
max_tx = (GLfloat) (geom.x + geom.width) / tw;
407
max_ty = (GLfloat) (geom.y + geom.height) / th;
409
qx = -QW/2 + ((GLfloat) geom.x * QW / iw);
410
qy = QH/2 - ((GLfloat) geom.y * QH / ih);
411
qw = QW * ((GLfloat) geom.width / iw);
412
qh = QH * ((GLfloat) geom.height / ih);
414
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
415
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
416
(mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
419
void init_screenflip(ModeInfo *mi)
421
int screen = MI_SCREEN(mi);
424
if (screenflip == NULL) {
425
if ((screenflip = (Screenflip *) calloc(MI_NUM_SCREENS(mi),
426
sizeof(Screenflip))) == NULL)
429
c = &screenflip[screen];
430
c->window = MI_WINDOW(mi);
432
trackball = gltrackball_init ();
434
if ((c->glx_context = init_GL(mi)) != NULL) {
435
reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
439
winh = MI_WIN_HEIGHT(mi);
440
winw = MI_WIN_WIDTH(mi);
441
glClearColor(0.0,0.0,0.0,0.0);
443
if (! MI_IS_WIREFRAME(mi))
445
glShadeModel(GL_SMOOTH);
446
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
447
glEnable(GL_DEPTH_TEST);
448
glEnable(GL_CULL_FACE);
450
glDisable(GL_LIGHTING);
456
void draw_screenflip(ModeInfo *mi)
458
Screenflip *c = &screenflip[MI_SCREEN(mi)];
459
Window w = MI_WINDOW(mi);
460
Display *disp = MI_DISPLAY(mi);
465
glXMakeCurrent(disp, w, *(c->glx_context));
470
display(MI_IS_WIREFRAME(mi));
472
if(mi->fps_p) do_fps(mi);
474
glXSwapBuffers(disp, w);
477
void release_screenflip(ModeInfo *mi)
479
if (screenflip != NULL) {
480
(void) free((void *) screenflip);