From http://www.jwz.org/xscreensaver/xscreensaver-5.37.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 # define release_stonerview 0
29 #undef countof
30 #define countof(x) (sizeof((x))/sizeof((*x)))
31
32 #include "xlockmore.h"
33
34 #ifdef USE_GL /* whole file */
35
36 #include "stonerview.h"
37 #include "gltrackball.h"
38
39 #define DEF_TRANSPARENT "True"
40
41 typedef struct {
42   GLXContext *glx_context;
43   stonerview_state *st;
44   trackball_state *trackball;
45   Bool button_down_p;
46 } stonerview_configuration;
47
48 static stonerview_configuration *bps = NULL;
49
50 static Bool transparent_p;
51
52
53 static XrmOptionDescRec opts[] = {
54   { "-transparent",   ".transparent",   XrmoptionNoArg, "True" },
55   { "+transparent",   ".transparent",   XrmoptionNoArg, "False" },
56 };
57
58 static argtype vars[] = {
59   {&transparent_p, "transparent", "Transparent", DEF_TRANSPARENT, t_Bool},
60 };
61
62 ENTRYPOINT ModeSpecOpt stonerview_opts = {countof(opts), opts, countof(vars), vars, NULL};
63
64
65 ENTRYPOINT void
66 reshape_stonerview (ModeInfo *mi, int width, int height)
67 {
68   GLfloat h = (GLfloat) height / (GLfloat) width;
69
70   glViewport(0, 0, (GLint) width, (GLint) height);
71   glMatrixMode(GL_PROJECTION);
72   glLoadIdentity();
73   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
74   glMatrixMode(GL_MODELVIEW);
75   glLoadIdentity();
76   glTranslatef(0.0, 0.0, -40.0);
77 }
78
79
80 static void
81 free_stonerview (ModeInfo *mi);
82
83
84 ENTRYPOINT void 
85 init_stonerview (ModeInfo *mi)
86 {
87   stonerview_configuration *bp;
88
89   MI_INIT (mi, bps, free_stonerview);
90
91   bp = &bps[MI_SCREEN(mi)];
92
93   bp->glx_context = init_GL(mi);
94
95   bp->trackball = gltrackball_init (False);
96   bp->st = stonerview_init_view(MI_IS_WIREFRAME(mi), transparent_p);
97   stonerview_init_move(bp->st);
98
99   reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
100   clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
101 }
102
103
104 ENTRYPOINT void
105 draw_stonerview (ModeInfo *mi)
106 {
107   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
108
109   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
110
111   glPushMatrix ();
112   glRotatef( current_device_rotation(), 0, 0, 1);
113   gltrackball_rotate (bp->trackball);
114
115 # ifdef HAVE_MOBILE     /* Keep it the same relative size when rotated. */
116   {
117     GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
118     int o = (int) current_device_rotation();
119     if (o != 0 && o != 180 && o != -180)
120       glScalef (h, h, h);
121   }
122 # endif
123
124   stonerview_win_draw(bp->st);
125   if (! bp->button_down_p)
126     stonerview_move_increment(bp->st);
127   glPopMatrix ();
128
129   mi->polygon_count = NUM_ELS;
130   if (mi->fps_p) do_fps (mi);
131   glFinish();
132
133   glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
134 }
135
136 static void
137 free_stonerview (ModeInfo *mi)
138 {
139   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
140   if (bp->st)
141     stonerview_win_release (bp->st);
142 }
143
144 ENTRYPOINT Bool
145 stonerview_handle_event (ModeInfo *mi, XEvent *event)
146 {
147   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
148
149   if (gltrackball_event_handler (event, bp->trackball,
150                                  MI_WIDTH (mi), MI_HEIGHT (mi),
151                                  &bp->button_down_p))
152     return True;
153
154   return False;
155 }
156
157 XSCREENSAVER_MODULE ("StonerView", stonerview)
158
159 #endif /* USE_GL */