/*
- * screenflip - takes snapshots of the screen and flips it around
+ * flipscreen3d - takes snapshots of the screen and flips it around
*
* version 1.0 - Oct 24, 2001
*
#ifdef STANDALONE
-# define PROGCLASS "Screenflip"
+# define PROGCLASS "FlipScreen3D"
# define HACK_INIT init_screenflip
# define HACK_DRAW draw_screenflip
# define HACK_RESHAPE reshape_screenflip
+# define HACK_HANDLE_EVENT screenflip_handle_event
+# define EVENT_MASK PointerMotionMask
# define screenflip_opts xlockmore_opts
/* insert defaults here */
-#define DEFAULTS "*delay: 20000 \n" \
- "*showFPS: False \n" \
- "*rotate: True \n" \
- "*wireframe: False \n" \
+#define DEFAULTS "*delay: 20000 \n" \
+ "*showFPS: False \n" \
+ "*rotate: True \n" \
+ "*wireframe: False \n" \
+ "*useSHM: True \n"
# include "xlockmore.h" /* from the xscreensaver distribution */
#else /* !STANDALONE */
int winw, winh;
int tw, th; /* texture width, height */
int tx, ty;
+GLfloat min_tx, min_ty;
GLfloat max_tx, max_ty;
#define QW 12
static XrmOptionDescRec opts[] = {
- {"+rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "false" },
- {"-rotate", ".screenflip.rotate", XrmoptionNoArg, (caddr_t) "true" },
+ {"+rotate", ".screenflip.rotate", XrmoptionNoArg, "false" },
+ {"-rotate", ".screenflip.rotate", XrmoptionNoArg, "true" },
};
static argtype vars[] = {
- {(caddr_t *) &rotate, "rotate", "Rotate", "True", t_Bool},
+ {&rotate, "rotate", "Rotate", "True", t_Bool},
};
#include <stdio.h>
#include <stdlib.h>
#include "grab-ximage.h"
+#include "gltrackball.h"
#ifndef M_PI
#define M_PI 3.14159265
int regrab = 0;
int fadetime = 0; /* fade before regrab */
+static trackball_state *trackball;
+static Bool button_down_p = False;
+
+
+Bool
+screenflip_handle_event (ModeInfo *mi, XEvent *event)
+{
+ if (event->xany.type == ButtonPress &&
+ event->xbutton.button == Button1)
+ {
+ button_down_p = True;
+ gltrackball_start (trackball,
+ event->xbutton.x, event->xbutton.y,
+ MI_WIDTH (mi), MI_HEIGHT (mi));
+ return True;
+ }
+ else if (event->xany.type == ButtonRelease &&
+ event->xbutton.button == Button1)
+ {
+ button_down_p = False;
+ return True;
+ }
+ else if (event->xany.type == ButtonPress &&
+ (event->xbutton.button == Button4 ||
+ event->xbutton.button == Button5))
+ {
+ gltrackball_mousewheel (trackball, event->xbutton.button, 10,
+ !!event->xbutton.state);
+ return True;
+ }
+ else if (event->xany.type == MotionNotify &&
+ button_down_p)
+ {
+ gltrackball_track (trackball,
+ event->xmotion.x, event->xmotion.y,
+ MI_WIDTH (mi), MI_HEIGHT (mi));
+ return True;
+ }
+
+ return False;
+}
+
/* draw the texture mapped quad (actually two back to back)*/
void showscreen(int frozen, int wire)
{
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;
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;
+ x = qx;
+ y = qy;
+ w = qx+qw;
+ h = qy-qh;
if (!frozen) {
w *= sin (stretch_val_x) + 1;
x *= sin (stretch_val_x) + 1;
+ if (!button_down_p) {
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;
+ if (!button_down_p && !fadetime) stretch_val_y += stretch_val_dy;
h *= sin (stretch_val_y) / 2 + 1;
y *= sin (stretch_val_y) / 2 + 1;
+ if (!button_down_p) {
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);
glBegin(wire ? GL_LINE_LOOP : 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);
+ glTexCoord2f(max_tx, max_ty); glVertex3f(w, h, 0);
+ glTexCoord2f(max_tx, min_ty); glVertex3f(w, y, 0);
+ glTexCoord2f(min_tx, min_ty); glVertex3f(x, y, 0);
+ glTexCoord2f(min_tx, max_ty); 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);
-
+ glTexCoord2f(min_tx, min_ty); glVertex3f(x, y, -0.05);
+ glTexCoord2f(max_tx, min_ty); glVertex3f(w, y, -0.05);
+ glTexCoord2f(max_tx, max_ty); glVertex3f(w, h, -0.05);
+ glTexCoord2f(min_tx, max_ty); glVertex3f(x, h, -0.05);
glEnd();
frozen = 0;
glTranslatef(5 * sin(theta), 5 * sin(rho), 10 * cos(gamma) - 10);
/* randomly change the speed */
- if (!(random() % 300)) {
+ if (!button_down_p && !(random() % 300)) {
if (random() % 2)
drho = 1/60 - (float)(random() % 100)/3000;
if (random() % 2)
if (random() % 2)
dgamma = 1/60 - (float)(random() % 100)/3000;
}
+ gltrackball_rotate (trackball);
if (rotate) glRotatef(rot, rx, ry, rz);
/* update variables with each frame */
- if (!fadetime) {
+ if(!button_down_p && !fadetime) {
theta += dtheta;
rho += drho;
gamma += dgamma;
rot = 0;
frozen = 1;
}
- if (!fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate change */
+ if (!button_down_p && !fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate change */
rx = (GLfloat)(random() % 100) / 100;
ry = (GLfloat)(random() % 100) / 100;
rz = (GLfloat)(random() % 100) / 100;
void getSnapshot (ModeInfo *modeinfo)
{
- XImage *ximage;
- int status;
+ Bool mipmap_p = True;
+ XRectangle geom;
+ int iw, ih;
if (MI_IS_WIREFRAME(modeinfo))
return;
- ximage = screen_to_ximage (modeinfo->xgwa.screen, modeinfo->window);
-
- qw = QW; qh = QH;
- tw = modeinfo->xgwa.width;
- th = modeinfo->xgwa.height;
-
-#if 0 /* jwz: this makes the image start off the bottom right of the screen */
- qx += (qw*tw/winw);
- qy -= (qh*th/winh);
-#endif
+ if (! screen_to_texture (modeinfo->xgwa.screen, modeinfo->window, 0, 0,
+ mipmap_p, NULL, &geom, &iw, &ih, &tw, &th))
+ exit (1);
- qw *= (GLfloat)tw/winw;
- qh *= (GLfloat)th/winh;
+ min_tx = (GLfloat) geom.x / tw;
+ min_ty = (GLfloat) geom.y / th;
+ max_tx = (GLfloat) (geom.x + geom.width) / tw;
+ max_ty = (GLfloat) (geom.y + geom.height) / th;
- max_tx = (GLfloat) tw / (GLfloat) ximage->width;
- max_ty = (GLfloat) th / (GLfloat) ximage->height;
+ qx = -QW/2 + ((GLfloat) geom.x * QW / iw);
+ qy = QH/2 - ((GLfloat) geom.y * QH / ih);
+ qw = QW * ((GLfloat) geom.width / iw);
+ qh = QH * ((GLfloat) geom.height / ih);
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR_MIPMAP_LINEAR);
-
- clear_gl_error();
- status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
- ximage->width, ximage->height,
- GL_RGBA, GL_UNSIGNED_BYTE, ximage->data);
-
- if (!status && glGetError())
- /* Some implementations of gluBuild2DMipmaps(), but set a GL error anyway.
- We could just call check_gl_error(), but that would exit. */
- status = -1;
-
- if (status)
- {
- const char *s = gluErrorString (status);
- fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
- progname, ximage->width, ximage->height,
- (s ? s : "(unknown)"));
- fprintf (stderr, "%s: turning on -wireframe.\n", progname);
- MI_IS_WIREFRAME(modeinfo) = 1;
- clear_gl_error();
- }
- check_gl_error("mipmapping"); /* should get a return code instead of a
- GL error, but just in case... */
-
- free(ximage->data);
- ximage->data = 0;
- XDestroyImage (ximage);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ (mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
}
void init_screenflip(ModeInfo *mi)
c = &screenflip[screen];
c->window = MI_WINDOW(mi);
+ trackball = gltrackball_init ();
+
if ((c->glx_context = init_GL(mi)) != NULL) {
reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
} else {
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
+ glCullFace(GL_BACK);
glDisable(GL_LIGHTING);
}