http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.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 typedef struct {
39   GLXContext *glx_context;
40   stonerview_state *st;
41   trackball_state *trackball;
42   Bool button_down_p;
43 } stonerview_configuration;
44
45 static stonerview_configuration *bps = NULL;
46
47 ENTRYPOINT ModeSpecOpt stonerview_opts = {0, NULL, 0, NULL, NULL};
48
49
50 ENTRYPOINT void
51 reshape_stonerview (ModeInfo *mi, int width, int height)
52 {
53   GLfloat h = (GLfloat) height / (GLfloat) width;
54
55   glViewport(0, 0, (GLint) width, (GLint) height);
56   glMatrixMode(GL_PROJECTION);
57   glLoadIdentity();
58   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
59   glMatrixMode(GL_MODELVIEW);
60   glLoadIdentity();
61   glTranslatef(0.0, 0.0, -40.0);
62 }
63
64
65 ENTRYPOINT void 
66 init_stonerview (ModeInfo *mi)
67 {
68   stonerview_configuration *bp;
69
70   if (!bps) {
71     bps = (stonerview_configuration *)
72       calloc (MI_NUM_SCREENS(mi), sizeof (stonerview_configuration));
73     if (!bps) {
74       fprintf(stderr, "%s: out of memory\n", progname);
75       exit(1);
76     }
77
78     bp = &bps[MI_SCREEN(mi)];
79   }
80
81   bp = &bps[MI_SCREEN(mi)];
82
83   bp->glx_context = init_GL(mi);
84
85   bp->trackball = gltrackball_init ();
86   bp->st = init_view(MI_IS_WIREFRAME(mi));
87   init_move(bp->st);
88
89   reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
90 }
91
92
93 ENTRYPOINT void
94 draw_stonerview (ModeInfo *mi)
95 {
96   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
97
98   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
99
100   glPushMatrix ();
101   gltrackball_rotate (bp->trackball);
102   win_draw(bp->st);
103   if (! bp->button_down_p)
104     move_increment(bp->st);
105   glPopMatrix ();
106
107   mi->polygon_count = NUM_ELS;
108   if (mi->fps_p) do_fps (mi);
109   glFinish();
110
111   glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
112 }
113
114 ENTRYPOINT void
115 release_stonerview (ModeInfo *mi)
116 {
117   if (bps) {
118     int screen;
119     for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
120       stonerview_configuration *bp = &bps[screen];
121       if (bp->st)
122         win_release (bp->st);
123     }
124     free (bps);
125     bps = 0;
126   }
127   FreeAllGL(mi);
128 }
129
130 ENTRYPOINT Bool
131 stonerview_handle_event (ModeInfo *mi, XEvent *event)
132 {
133   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
134
135   if (event->xany.type == ButtonPress &&
136       event->xbutton.button == Button1)
137     {
138       bp->button_down_p = True;
139       gltrackball_start (bp->trackball,
140                          event->xbutton.x, event->xbutton.y,
141                          MI_WIDTH (mi), MI_HEIGHT (mi));
142       return True;
143     }
144   else if (event->xany.type == ButtonRelease &&
145            event->xbutton.button == Button1)
146     {
147       bp->button_down_p = False;
148       return True;
149     }
150   else if (event->xany.type == ButtonPress &&
151            (event->xbutton.button == Button4 ||
152             event->xbutton.button == Button5 ||
153             event->xbutton.button == Button6 ||
154             event->xbutton.button == Button7))
155     {
156       gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10,
157                               !!event->xbutton.state);
158       return True;
159     }
160   else if (event->xany.type == MotionNotify &&
161            bp->button_down_p)
162     {
163       gltrackball_track (bp->trackball,
164                          event->xmotion.x, event->xmotion.y,
165                          MI_WIDTH (mi), MI_HEIGHT (mi));
166       return True;
167     }
168
169   return False;
170 }
171
172 XSCREENSAVER_MODULE ("StonerView", stonerview)
173
174 #endif /* USE_GL */