1 /* StonerView: An eccentric visual toy.
2 Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com)
4 For the latest version, source code, and links to more of my stuff, see:
5 http://www.eblong.com/zarf/stonerview.html
7 Permission to use, copy, modify, distribute, and sell this software and its
8 documentation for any purpose is hereby granted without fee, provided that
9 the above copyright notice appear in all copies and that both that
10 copyright notice and this permission notice appear in supporting
11 documentation. No representations are made about the suitability of this
12 software for any purpose. It is provided "as is" without express or
16 /* Ported away from GLUT (so that it can do `-root' and work with xscreensaver)
17 by Jamie Zawinski <jwz@jwz.org>, 22-Jan-2001.
19 Revamped to work in the xlockmore framework so that it will also work
20 with the MacOS X port of xscreensaver by jwz, 21-Feb-2006.
23 #define DEFAULTS "*delay: 20000 \n" \
24 "*showFPS: False \n" \
25 "*wireframe: False \n"
27 # define refresh_stonerview 0
29 #define countof(x) (sizeof((x))/sizeof((*x)))
31 #include "xlockmore.h"
33 #ifdef USE_GL /* whole file */
35 #include "stonerview.h"
36 #include "gltrackball.h"
38 #define DEF_TRANSPARENT "True"
41 GLXContext *glx_context;
43 trackball_state *trackball;
45 } stonerview_configuration;
47 static stonerview_configuration *bps = NULL;
49 static Bool transparent_p;
52 static XrmOptionDescRec opts[] = {
53 { "-transparent", ".transparent", XrmoptionNoArg, "True" },
54 { "+transparent", ".transparent", XrmoptionNoArg, "False" },
57 static argtype vars[] = {
58 {&transparent_p, "transparent", "Transparent", DEF_TRANSPARENT, t_Bool},
61 ENTRYPOINT ModeSpecOpt stonerview_opts = {countof(opts), opts, countof(vars), vars, NULL};
65 reshape_stonerview (ModeInfo *mi, int width, int height)
67 GLfloat h = (GLfloat) height / (GLfloat) width;
69 glViewport(0, 0, (GLint) width, (GLint) height);
70 glMatrixMode(GL_PROJECTION);
72 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
73 glMatrixMode(GL_MODELVIEW);
75 glTranslatef(0.0, 0.0, -40.0);
80 init_stonerview (ModeInfo *mi)
82 stonerview_configuration *bp;
85 bps = (stonerview_configuration *)
86 calloc (MI_NUM_SCREENS(mi), sizeof (stonerview_configuration));
88 fprintf(stderr, "%s: out of memory\n", progname);
93 bp = &bps[MI_SCREEN(mi)];
95 bp->glx_context = init_GL(mi);
97 bp->trackball = gltrackball_init ();
98 bp->st = init_view(MI_IS_WIREFRAME(mi), transparent_p);
101 reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
106 draw_stonerview (ModeInfo *mi)
108 stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
110 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
113 gltrackball_rotate (bp->trackball);
115 if (! bp->button_down_p)
116 move_increment(bp->st);
119 mi->polygon_count = NUM_ELS;
120 if (mi->fps_p) do_fps (mi);
123 glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
127 release_stonerview (ModeInfo *mi)
131 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
132 stonerview_configuration *bp = &bps[screen];
134 win_release (bp->st);
143 stonerview_handle_event (ModeInfo *mi, XEvent *event)
145 stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
147 if (event->xany.type == ButtonPress &&
148 event->xbutton.button == Button1)
150 bp->button_down_p = True;
151 gltrackball_start (bp->trackball,
152 event->xbutton.x, event->xbutton.y,
153 MI_WIDTH (mi), MI_HEIGHT (mi));
156 else if (event->xany.type == ButtonRelease &&
157 event->xbutton.button == Button1)
159 bp->button_down_p = False;
162 else if (event->xany.type == ButtonPress &&
163 (event->xbutton.button == Button4 ||
164 event->xbutton.button == Button5 ||
165 event->xbutton.button == Button6 ||
166 event->xbutton.button == Button7))
168 gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10,
169 !!event->xbutton.state);
172 else if (event->xany.type == MotionNotify &&
175 gltrackball_track (bp->trackball,
176 event->xmotion.x, event->xmotion.y,
177 MI_WIDTH (mi), MI_HEIGHT (mi));
184 XSCREENSAVER_MODULE ("StonerView", stonerview)