From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / b_lockglue.c
1 #if 0
2 static const char sccsid[] = "@(#)b_lockglue.c  4.11 98/06/16 xlockmore";
3 #endif
4
5 /*-
6  * BUBBLE3D (C) 1998 Richard W.M. Jones.
7  * b_lockglue.c: Glue to make this all work with xlockmore.
8  */
9
10 #include "bubble3d.h"
11
12 /* XXX This lot should eventually be made configurable using the
13  * options stuff below.
14  */
15 struct glb_config glb_config =
16 {
17         0,                      /* transparent_p */
18 #if GLB_SLOW_GL
19         2,                      /* subdivision_depth */
20 #else
21         3,                      /* subdivision_depth */
22 #endif
23         5,                      /* nr_nudge_axes */
24         0.01,                   /* nudge_angle_factor */
25         0.20,                   /* nudge_factor */
26         0.1,                    /* rotation_factor */
27         8,                      /* create_bubbles_every */
28         8,                      /* max_bubbles */
29         {0.7, 0.8, 0.9, 1.0},   /* p_bubble_group */
30         0.5,                    /* max_size */
31         0.1,                    /* min_size */
32         0.03,                   /* max_speed */
33         0.005,                  /* min_speed */
34         1.5,                    /* scale_factor */
35         -4,                     /* screen_bottom */
36         4,                      /* screen_top */
37         {0.0, 0.0, 0.7, 0.3}    /* bubble_colour */
38 };
39
40 #ifdef STANDALONE
41 # define DEFAULTS       "*delay:        10000   \n"     \
42                         "*showFPS:      False   \n"
43
44 # define refresh_bubble3d 0
45 # define release_bubble3d 0
46 # define bubble3d_handle_event 0
47 #include "xlockmore.h"
48 #else
49 #include "xlock.h"
50 #include "vis.h"
51 #endif
52
53 #ifdef USE_GL
54
55
56 #define DEF_TRANSPARENT "True"
57 #define DEF_BUBBLECOLOR "random"
58
59 static Bool transparent_p;
60 static char *bubble_color_str;
61
62 #undef countof
63 #define countof(x) (sizeof((x))/sizeof((*x)))
64
65 static XrmOptionDescRec opts[] = {
66   { "-transparent",  ".transparent",   XrmoptionNoArg, "True" },
67   { "+transparent",  ".transparent",   XrmoptionNoArg, "False" },
68   { "-color",        ".bubblecolor",   XrmoptionSepArg, 0 },
69 };
70
71 static argtype vars[] = {
72   {&transparent_p,   "transparent", "Transparent", DEF_TRANSPARENT, t_Bool},
73   {&bubble_color_str,        "bubblecolor", "BubbleColor", DEF_BUBBLECOLOR, t_String},
74 };
75
76 ENTRYPOINT ModeSpecOpt bubble3d_opts = {countof(opts), opts, countof(vars), vars, NULL};
77
78 #ifdef USE_MODULES
79 ModStruct   bubbles3d_description =
80 {"bubbles3d",
81  "init_bubble3d",
82  "draw_bubble3d",
83  NULL,
84  "change_bubble3d",
85  "init_bubble3d",
86  NULL,
87  &bubble3d_opts,
88  1000, 1, 2, 1, 64, 1.0, "",
89  "Richard Jones's GL bubbles",
90  0,
91  NULL
92 };
93
94 #endif /* USE_MODULES */
95
96 struct context {
97         GLXContext *glx_context;
98         void       *draw_context;
99 };
100
101 static struct context *contexts = 0;
102
103 static void
104 parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a)
105 {
106   XColor c;
107
108   if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c))
109     {
110       fprintf (stderr, "%s: can't parse %s color %s", progname, name, s);
111       exit (1);
112     }
113   a[0] = c.red   / 65536.0;
114   a[1] = c.green / 65536.0;
115   a[2] = c.blue  / 65536.0;
116 }
117
118 static void
119 init_colors(ModeInfo *mi)
120 {
121         if (strncasecmp(bubble_color_str, "auto", strlen("auto")) == 0) {
122                 glb_config.bubble_colour[0] = ((float) (NRAND(100)) / 100.0);
123                 glb_config.bubble_colour[1] = ((float) (NRAND(100)) / 100.0);
124                 /* I keep more blue */
125                 glb_config.bubble_colour[2] = ((float) (NRAND(50)) / 100.0) + 0.50;
126         } else if (strncasecmp(bubble_color_str, "random", strlen("random")) == 0) {
127             glb_config.bubble_colour[0] = -1.0;
128         } else {
129                 parse_color(mi, "bubble", bubble_color_str, glb_config.bubble_colour);
130         }
131 }
132
133 static void
134 init(struct context *c)
135 {
136         glb_config.transparent_p = transparent_p;
137         glb_sphere_init();
138         c->draw_context = glb_draw_init();
139 }
140
141 ENTRYPOINT void
142 reshape_bubble3d(ModeInfo *mi, int w, int h)
143 {
144         glViewport(0, 0, (GLsizei) w, (GLsizei) h);
145         glMatrixMode(GL_PROJECTION);
146         glLoadIdentity();
147         gluPerspective(45, (GLdouble) w / (GLdouble) h, 3, 8);
148         glMatrixMode(GL_MODELVIEW);
149         glLoadIdentity();
150         glTranslatef(0, 0, -5);
151 }
152
153 static void
154 do_display(struct context *c)
155 {
156         glb_draw_step(c->draw_context);
157 }
158
159 static void free_bubble3d(ModeInfo * mi);
160
161 ENTRYPOINT void
162 init_bubble3d(ModeInfo * mi)
163 {
164         Display    *display = MI_DISPLAY(mi);
165         Window      window = MI_WINDOW(mi);
166         int         screen = MI_SCREEN(mi);
167         struct context *c;
168
169         MI_INIT (mi, contexts, free_bubble3d);
170         c = &contexts[screen];
171         c->glx_context = init_GL(mi);
172         init_colors(mi);
173         if (c->glx_context != 0) {
174                 init(c);
175                 reshape_bubble3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
176                 do_display(c);
177                 glFinish();
178                 glXSwapBuffers(display, window);
179         } else
180                 MI_CLEARWINDOW(mi);
181 }
182
183 ENTRYPOINT void
184 draw_bubble3d(ModeInfo * mi)
185 {
186         struct context *c = &contexts[MI_SCREEN(mi)];
187         Display    *display = MI_DISPLAY(mi);
188         Window      window = MI_WINDOW(mi);
189
190         MI_IS_DRAWN(mi) = True;
191
192         if (!c->glx_context)
193                 return;
194
195         glXMakeCurrent(display, window, *(c->glx_context));
196
197         glb_config.polygon_count = 0;
198         glPushMatrix();
199
200 # ifdef HAVE_MOBILE     /* Keep it the same relative size when rotated. */
201         {
202           GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
203           int o = (int) current_device_rotation();
204           if (o != 0 && o != 180 && o != -180)
205             glScalef (1/h, 1/h, 1/h);
206           glRotatef(o, 0, 0, 1);
207         }
208 # endif
209
210         do_display(c);
211         glPopMatrix();
212         mi->polygon_count = glb_config.polygon_count;
213
214         if (mi->fps_p) do_fps (mi);
215         glFinish();
216         glXSwapBuffers(display, window);
217 }
218
219 #ifndef STANDALONE
220 ENTRYPOINT void
221 change_bubble3d(ModeInfo * mi)
222 {
223         /* nothing */
224 }
225 #endif /* !STANDALONE */
226
227 static void
228 free_bubble3d(ModeInfo * mi)
229 {
230   struct context *c = &contexts[MI_SCREEN(mi)];
231   if (c->draw_context)
232     glb_draw_end(c->draw_context);
233 }
234
235 XSCREENSAVER_MODULE ("Bubble3D", bubble3d)
236
237 #endif /* USE_GL */