From http://www.jwz.org/xscreensaver/xscreensaver-5.38.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 release_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   MI_INIT (mi, bps);
85
86   bp = &bps[MI_SCREEN(mi)];
87
88   bp->glx_context = init_GL(mi);
89
90   bp->trackball = gltrackball_init (False);
91   bp->st = stonerview_init_view(MI_IS_WIREFRAME(mi), transparent_p);
92   stonerview_init_move(bp->st);
93
94   reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
95   clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
96 }
97
98
99 ENTRYPOINT void
100 draw_stonerview (ModeInfo *mi)
101 {
102   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
103
104   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
105
106   glPushMatrix ();
107   glRotatef( current_device_rotation(), 0, 0, 1);
108   gltrackball_rotate (bp->trackball);
109
110 # ifdef HAVE_MOBILE     /* Keep it the same relative size when rotated. */
111   {
112     GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
113     int o = (int) current_device_rotation();
114     if (o != 0 && o != 180 && o != -180)
115       glScalef (h, h, h);
116   }
117 # endif
118
119   stonerview_win_draw(bp->st);
120   if (! bp->button_down_p)
121     stonerview_move_increment(bp->st);
122   glPopMatrix ();
123
124   mi->polygon_count = NUM_ELS;
125   if (mi->fps_p) do_fps (mi);
126   glFinish();
127
128   glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
129 }
130
131 ENTRYPOINT void
132 free_stonerview (ModeInfo *mi)
133 {
134   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
135   if (bp->st)
136     stonerview_win_release (bp->st);
137 }
138
139 ENTRYPOINT Bool
140 stonerview_handle_event (ModeInfo *mi, XEvent *event)
141 {
142   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
143
144   if (gltrackball_event_handler (event, bp->trackball,
145                                  MI_WIDTH (mi), MI_HEIGHT (mi),
146                                  &bp->button_down_p))
147     return True;
148
149   return False;
150 }
151
152 XSCREENSAVER_MODULE ("StonerView", stonerview)
153
154 #endif /* USE_GL */