From http://www.jwz.org/xscreensaver/xscreensaver-5.30.tar.gz
[xscreensaver] / hacks / glx / stonerview.c
1 /* StonerView: An eccentric visual toy.
2    Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com)
3
4    For the latest version, source code, and links to more of my stuff, see:
5    http://www.eblong.com/zarf/stonerview.html
6
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 
13    implied warranty.
14 */
15
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.
18
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.
21  */
22
23 #define DEFAULTS        "*delay:        20000       \n" \
24                         "*showFPS:      False       \n" \
25                         "*wireframe:    False       \n"
26
27 # define refresh_stonerview 0
28 #undef countof
29 #define countof(x) (sizeof((x))/sizeof((*x)))
30
31 #include "xlockmore.h"
32
33 #ifdef USE_GL /* whole file */
34
35 #include "stonerview.h"
36 #include "gltrackball.h"
37
38 #define DEF_TRANSPARENT "True"
39
40 typedef struct {
41   GLXContext *glx_context;
42   stonerview_state *st;
43   trackball_state *trackball;
44   Bool button_down_p;
45 } stonerview_configuration;
46
47 static stonerview_configuration *bps = NULL;
48
49 static Bool transparent_p;
50
51
52 static XrmOptionDescRec opts[] = {
53   { "-transparent",   ".transparent",   XrmoptionNoArg, "True" },
54   { "+transparent",   ".transparent",   XrmoptionNoArg, "False" },
55 };
56
57 static argtype vars[] = {
58   {&transparent_p, "transparent", "Transparent", DEF_TRANSPARENT, t_Bool},
59 };
60
61 ENTRYPOINT ModeSpecOpt stonerview_opts = {countof(opts), opts, countof(vars), vars, NULL};
62
63
64 ENTRYPOINT void
65 reshape_stonerview (ModeInfo *mi, int width, int height)
66 {
67   GLfloat h = (GLfloat) height / (GLfloat) width;
68
69   glViewport(0, 0, (GLint) width, (GLint) height);
70   glMatrixMode(GL_PROJECTION);
71   glLoadIdentity();
72   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
73   glMatrixMode(GL_MODELVIEW);
74   glLoadIdentity();
75   glTranslatef(0.0, 0.0, -40.0);
76 }
77
78
79 ENTRYPOINT void 
80 init_stonerview (ModeInfo *mi)
81 {
82   stonerview_configuration *bp;
83
84   if (!bps) {
85     bps = (stonerview_configuration *)
86       calloc (MI_NUM_SCREENS(mi), sizeof (stonerview_configuration));
87     if (!bps) {
88       fprintf(stderr, "%s: out of memory\n", progname);
89       exit(1);
90     }
91   }
92
93   bp = &bps[MI_SCREEN(mi)];
94
95   bp->glx_context = init_GL(mi);
96
97   bp->trackball = gltrackball_init (False);
98   bp->st = stonerview_init_view(MI_IS_WIREFRAME(mi), transparent_p);
99   stonerview_init_move(bp->st);
100
101   reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
102   clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
103 }
104
105
106 ENTRYPOINT void
107 draw_stonerview (ModeInfo *mi)
108 {
109   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
110
111   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
112
113   glPushMatrix ();
114   glRotatef( current_device_rotation(), 0, 0, 1);
115   gltrackball_rotate (bp->trackball);
116
117   stonerview_win_draw(bp->st);
118   if (! bp->button_down_p)
119     stonerview_move_increment(bp->st);
120   glPopMatrix ();
121
122   mi->polygon_count = NUM_ELS;
123   if (mi->fps_p) do_fps (mi);
124   glFinish();
125
126   glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
127 }
128
129 ENTRYPOINT void
130 release_stonerview (ModeInfo *mi)
131 {
132   if (bps) {
133     int screen;
134     for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
135       stonerview_configuration *bp = &bps[screen];
136       if (bp->st)
137         stonerview_win_release (bp->st);
138     }
139     free (bps);
140     bps = 0;
141   }
142   FreeAllGL(mi);
143 }
144
145 ENTRYPOINT Bool
146 stonerview_handle_event (ModeInfo *mi, XEvent *event)
147 {
148   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
149
150   if (gltrackball_event_handler (event, bp->trackball,
151                                  MI_WIDTH (mi), MI_HEIGHT (mi),
152                                  &bp->button_down_p))
153     return True;
154
155   return False;
156 }
157
158 XSCREENSAVER_MODULE ("StonerView", stonerview)
159
160 #endif /* USE_GL */