1 /* sballs --- balls spinning like crazy in GL */
2
3 #if 0
4 static const char sccsid[] = "@(#)sballs.c 5.02 2001/03/10 xlockmore";
5 #endif
6
7 /* Copyright (c) E. Lassauge, 2001. */
8
9 /*
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
15 *
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
21 *
22 * The original code for this mode was written by
23 * Mustata Bogdan (LoneRunner) <lonerunner@planetquake.com>
24 * and can be found at http://www.cfxweb.net/lonerunner/
25 *
26 * Eric Lassauge (November-07-2000) <lassauge@users.sourceforge.net>
27 * http://lassauge.free.fr/linux.html
28 *
29 * REVISION HISTORY:
30 *
31 * E.Lassauge - 03-Oct-2001:
32 * - minor bugfixes - get ready for xscreensaver
33 * E.Lassauge - 09-Mar-2001:
34 * - get rid of my framerate options to use showfps
35 * E.Lassauge - 28-Nov-2000:
36 * - add handling of polyhedrons (like in ico)
37 * - modified release part to add freeing of GL objects
38 * E.Lassauge - 14-Nov-2000:
39 * - use new common xpm_to_ximage function
40 *
41 */
42
43 #ifdef STANDALONE /* xscreensaver mode */
44 #define DEFAULTS "*delay: 30000 \n" \
45 "*size: 0 \n" \
46 "*cycles: 4 \n" \
47 "*showFPS: False \n" \
48 "*wireframe: False \n" \
49
50 # define release_sballs 0
51 #define MODE_sballs
52 #include "xlockmore.h" /* from the xscreensaver distribution */
53 #include "gltrackball.h"
54 #else /* !STANDALONE */
55 #include "xlock.h" /* from the xlockmore distribution */
56 #include "visgl.h"
57 #endif /* !STANDALONE */
58
59 #define MINSIZE 32 /* minimal viewport size */
60 #define FRAME 50 /* frame count interval */
61 #define MAX_OBJ 8 /* number of 3D objects */
62
63 #if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( STANDALONE )
64 /* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */
65 # include "ximage-loader.h"
66 # define I_HAVE_XPM
67
68 # include "images/gen/sball_png.h"
69 # include "images/gen/sball-bg_png.h"
70
71 /* Manage option vars */
72 #define DEF_TEXTURE "True"
73 #define DEF_OBJECT "0"
74 static Bool do_texture;
75 static int object, object_arg;
76 static int spheres;
77
78 static XrmOptionDescRec opts[] = {
79 {"-texture", ".sballs.texture", XrmoptionNoArg, "on"},
80 {"+texture", ".sballs.texture", XrmoptionNoArg, "off"},
81 {"-object", ".sballs.object", XrmoptionSepArg, 0},
82
83 };
84
85 static argtype vars[] = {
86 {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
87 {&object_arg, "object", "Object", DEF_OBJECT, t_Int},
88
89 };
90
91 static OptionStruct desc[] = {
92 /*{"-count spheres", "set number of spheres"},*/
93 /*{"-cycles speed", "set ball speed value"},*/
94 {"-/+texture", "turn on/off texturing"},
95 {"-object num", "number of the 3D object (0 means random)"},
96 };
97
98 ENTRYPOINT ModeSpecOpt sballs_opts =
99 { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc };
100
101 #ifdef USE_MODULES
102 ModStruct sballs_description =
103 { "sballs", "init_sballs", "draw_sballs", NULL,
104 "draw_sballs", "change_sballs", "free_sballs", &sballs_opts,
105 /*
106 delay,count,cycles,size,ncolors,sat
107 */
108 10000, 0, 10, 400, 64, 1.0, "",
109 "balls spinning like crazy in GL", 0, NULL
110 };
111 #endif /* USE_MODULES */
112
113 /* misc types and defines */
114 #define vinit(a,i,j,k) {\
115 (a)[0]=i;\
116 (a)[1]=j;\
117 (a)[2]=k;\
118 }
119 typedef float vec_t;
120 typedef vec_t vec3_t[3];
121
122 #define MAX_BALLS 20
123
124 /* the mode struct, contains all per screen variables */
125 typedef struct {
126 GLint WIDTH, HEIGHT; /* display dimensions */
127 GLXContext *glx_context;
128
129
130 XImage *btexture; /* back texture image bits */
131 XImage *ftexture; /* face texture image bits */
132 GLuint backid; /* back texture id: GL world */
133 GLuint faceid; /* face texture id: GL world */
134
135 vec3_t eye;
136 vec3_t rotm;
137 int speed;
138 float radius[MAX_BALLS];
139
140 trackball_state *trackball;
141 Bool button_down_p;
142
143 } sballsstruct;
144
145 /* array of sballsstruct indexed by screen number */
146 static sballsstruct *sballs = (sballsstruct *) NULL;
147
148 /* lights */
149 static const float LightAmbient[]= { 1.0f, 1.0f, 1.0f, 1.0f };
150 static const float LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
151 static const float LightPosition[]= { 0.0f, 0.0f, 4.0f, 1.0f };
152
153 /* structure of the polyhedras */
154 typedef struct {
155 const char *longname; /* long name of object */
156 const char *shortname; /* short name of object */
157 int numverts; /* number of vertices */
158 float radius; /* radius */
159 vec3_t v[MAX_BALLS];/* the vertices */
160 } Polyinfo;
161
162 static const Polyinfo polygons[] =
163 {
164
165 /* 0: objtetra - structure values for tetrahedron */
166 {
167 "tetrahedron", "tetra", /* long and short names */
168 4, /* number of vertices */
169 0.8,
170 { /* vertices (x,y,z) */
171 /* all points must be within radius 2 of the origin */
172 #define T 1.0
173 {T, T, T},
174 {T, -T, -T},
175 {-T, T, -T},
176 {-T, -T, T},
177 #undef T
178 }
179 },
180
181 /* 1: objcube - structure values for cube */
182
183 {
184 "hexahedron", "cube", /* long and short names */
185 8, /* number of vertices, edges, and faces */
186 0.6,
187 { /* vertices (x,y,z) */
188 /* all points must be within radius 2 of the origin */
189 #define T 1.0
190 {T, T, T},
191 {T, T, -T},
192 {T, -T, -T},
193 {T, -T, T},
194 {-T, T, T},
195 {-T, T, -T},
196 {-T, -T, -T},
197 {-T, -T, T},
198 #undef T
199 }
200 },
201
202 /* 2: objocta - structure values for octahedron */
203
204 {
205 "octahedron", "octa", /* long and short names */
206 6, /* number of vertices */
207 0.6,
208 { /* vertices (x,y,z) */
209 /* all points must be within radius 2 of the origin */
210 #define T 1.5
211 {T, 0, 0},
212 {-T, 0, 0},
213 {0, T, 0},
214 {0, -T, 0},
215 {0, 0, T},
216 {0, 0, -T},
217 #undef T
218 }
219 },
220 /* 3: objdodec - structure values for dodecahedron */
221
222 {
223 "dodecahedron", "dodeca", /* long and short names */
224 20, /* number of vertices */
225 0.35,
226 { /* vertices (x,y,z) */
227 /* all points must be within radius 2 of the origin */
228 {0.000000, 0.500000, 1.000000},
229 {0.000000, -0.500000, 1.000000},
230 {0.000000, -0.500000, -1.000000},
231 {0.000000, 0.500000, -1.000000},
232 {1.000000, 0.000000, 0.500000},
233 {-1.000000, 0.000000, 0.500000},
234 {-1.000000, 0.000000, -0.500000},
235 {1.000000, 0.000000, -0.500000},
236 {0.500000, 1.000000, 0.000000},
237 {-0.500000, 1.000000, 0.000000},
238 {-0.500000, -1.000000, 0.000000},
239 {0.500000, -1.000000, 0.000000},
240 {0.750000, 0.750000, 0.750000},
241 {-0.750000, 0.750000, 0.750000},
242 {-0.750000, -0.750000, 0.750000},
243 {0.750000, -0.750000, 0.750000},
244 {0.750000, -0.750000, -0.750000},
245 {0.750000, 0.750000, -0.750000},
246 {-0.750000, 0.750000, -0.750000},
247 {-0.750000, -0.750000, -0.750000},
248 }
249 },
250
251 /* 4: objicosa - structure values for icosahedron */
252
253 {
254 "icosahedron", "icosa", /* long and short names */
255 12, /* number of vertices */
256 0.4,
257 { /* vertices (x,y,z) */
258 /* all points must be within radius 2 of the origin */
259 {0.00000000, 0.00000000, -0.95105650},
260 {0.00000000, 0.85065080, -0.42532537},
261 {0.80901698, 0.26286556, -0.42532537},
262 {0.50000000, -0.68819095, -0.42532537},
263 {-0.50000000, -0.68819095, -0.42532537},
264 {-0.80901698, 0.26286556, -0.42532537},
265 {0.50000000, 0.68819095, 0.42532537},
266 {0.80901698, -0.26286556, 0.42532537},
267 {0.00000000, -0.85065080, 0.42532537},
268 {-0.80901698, -0.26286556, 0.42532537},
269 {-0.50000000, 0.68819095, 0.42532537},
270 {0.00000000, 0.00000000, 0.95105650}
271 }
272 },
273
274 /* 5: objplane - structure values for plane */
275
276 {
277 "plane", "plane", /* long and short names */
278 4, /* number of vertices */
279 0.7,
280 { /* vertices (x,y,z) */
281 /* all points must be within radius 2 of the origin */
282 #define T 1.1
283 {T, 0, 0},
284 {-T, 0, 0},
285 {0, T, 0},
286 {0, -T, 0},
287 #undef T
288 }
289 },
290
291 /* 6: objpyr - structure values for pyramid */
292
293 {
294 "pyramid", "pyramid", /* long and short names */
295 5, /* number of vertices */
296 0.5,
297 { /* vertices (x,y,z) */
298 /* all points must be within radius 1 of the origin */
299 #define T 1.0
300 {T, 0, 0},
301 {-T, 0, 0},
302 {0, T, 0},
303 {0, -T, 0},
304 {0, 0, T},
305 #undef T
306 }
307 },
308
309 /* 7: objstar - structure values for octahedron star (stellated octahedron?) */
310 {
311 "star", "star", /* long and short names */
312 8, /* number of vertices */
313 0.7,
314 { /* vertices (x,y,z) */
315 /* all points must be within radius 1 of the origin */
316 #define T 0.9
317 {T, T, T},
318 {T, -T, -T},
319 {-T, T, -T},
320 {-T, -T, T},
321 {-T, -T, -T},
322 {-T, T, T},
323 {T, -T, T},
324 {T, T, -T},
325 #undef T
326 }
327 },
328
329 };
330
331
332
333
334 /*
335 *-----------------------------------------------------------------------------
336 *-----------------------------------------------------------------------------
337 * Misc funcs.
338 *-----------------------------------------------------------------------------
339 *-----------------------------------------------------------------------------
340 */
341
342
343 /* initialise textures */
inittextures(ModeInfo * mi)344 static void inittextures(ModeInfo * mi)
345 {
346 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
347
348 #if defined( I_HAVE_XPM )
349 if (do_texture) {
350
351 glGenTextures(1, &sb->backid);
352 #ifdef HAVE_GLBINDTEXTURE
353 glBindTexture(GL_TEXTURE_2D, sb->backid);
354 #endif /* HAVE_GLBINDTEXTURE */
355
356 sb->btexture = image_data_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
357 sball_bg_png,
358 sizeof(sball_bg_png));
359 if (!(sb->btexture)) {
360 (void) fprintf(stderr, "Error reading the background texture.\n");
361 glDeleteTextures(1, &sb->backid);
362 do_texture = False;
363 sb->faceid = 0; /* default textures */
364 sb->backid = 0;
365 return;
366 }
367
368 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
369 clear_gl_error();
370 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
371 sb->btexture->width, sb->btexture->height, 0,
372 GL_RGBA, GL_UNSIGNED_BYTE, sb->btexture->data);
373 check_gl_error("texture");
374
375 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
376 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
377
378 /*
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
381 Let's pixellate it instead:
382 */
383 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
385
386 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
387
388 glGenTextures(1, &sb->faceid);
389 #ifdef HAVE_GLBINDTEXTURE
390 glBindTexture(GL_TEXTURE_2D, sb->faceid);
391 #endif /* HAVE_GLBINDTEXTURE */
392
393 sb->ftexture = image_data_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
394 sball_png, sizeof(sball_png));
395 if (!(sb->ftexture)) {
396 (void) fprintf(stderr, "Error reading the face texture.\n");
397 glDeleteTextures(1, &sb->faceid);
398 sb->faceid = 0;
399 return;
400 }
401
402 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
403 clear_gl_error();
404 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
405 sb->ftexture->width, sb->ftexture->height, 0,
406 GL_RGBA, GL_UNSIGNED_BYTE, sb->ftexture->data);
407 check_gl_error("texture");
408
409 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
410 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
411
412 /*
413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
415 Let's pixellate it instead:
416 */
417 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
418 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
419
420 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
421 }
422 else
423 {
424 sb->faceid = 0; /* default textures */
425 sb->backid = 0;
426 }
427 #else /* !I_HAVE_XPM */
428 do_texture = False;
429 sb->faceid = 0; /* default textures */
430 sb->backid = 0;
431 #endif /* !I_HAVE_XPM */
432 }
433
drawSphere(ModeInfo * mi,int sphere_num)434 static void drawSphere(ModeInfo * mi,int sphere_num)
435 {
436 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
437 float x = polygons[object].v[sphere_num][0];
438 float y = polygons[object].v[sphere_num][1];
439 float z = polygons[object].v[sphere_num][2];
440 int numMajor = 15;
441 int numMinor = 30;
442 float radius = sb->radius[sphere_num];
443 double majorStep = (M_PI / numMajor);
444 double minorStep = (2.0 * M_PI / numMinor);
445 int i, j;
446
447 glPushMatrix();
448 glTranslatef(x, y, z);
449
450 glColor4f(1, 1, 1, 1);
451 for (i = 0; i < numMajor; ++i)
452 {
453 double a = i * majorStep;
454 double b = a + majorStep;
455 double r0 = radius * sin(a);
456 double r1 = radius * sin(b);
457 GLfloat z0 = radius * cos(a);
458 GLfloat z1 = radius * cos(b);
459
460 glBegin(MI_IS_WIREFRAME(mi) ? GL_LINE_STRIP: GL_TRIANGLE_STRIP);
461 for (j = 0; j <= numMinor; ++j)
462 {
463 double c = j * minorStep;
464 GLfloat x = cos(c);
465 GLfloat y = sin(c);
466
467 glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
468 glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
469 glVertex3f(x * r0, y * r0, z0);
470
471 glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
472 glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
473 glVertex3f(x * r1, y * r1, z1);
474
475 mi->polygon_count++;
476 }
477 glEnd();
478 }
479
480 glPopMatrix();
481 }
482
483 /*
484 *-----------------------------------------------------------------------------
485 *-----------------------------------------------------------------------------
486 * GL funcs.
487 *-----------------------------------------------------------------------------
488 *-----------------------------------------------------------------------------
489 */
490
491 #ifndef STANDALONE
Reshape(ModeInfo * mi)492 static void Reshape(ModeInfo * mi)
493 #else
494 ENTRYPOINT void reshape_sballs(ModeInfo * mi, int width, int height)
495 #endif
496 {
497
498 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
499 int size = MI_SIZE(mi);
500
501 /* Viewport is specified size if size >= MINSIZE && size < screensize */
502 if (size <= 1) {
503 sb->WIDTH = MI_WIDTH(mi);
504 sb->HEIGHT = MI_HEIGHT(mi);
505 } else if (size < MINSIZE) {
506 sb->WIDTH = MINSIZE;
507 sb->HEIGHT = MINSIZE;
508 } else {
509 sb->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
510 sb->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
511 }
512
513 if (width > height * 5) { /* tiny window: show middle */
514 sb->WIDTH = width;
515 sb->HEIGHT = sb->WIDTH*0.75;
516 }
517
518 glViewport((MI_WIDTH(mi) - sb->WIDTH) / 2, (MI_HEIGHT(mi) - sb->HEIGHT) / 2, sb->WIDTH, sb->HEIGHT);
519 glMatrixMode(GL_PROJECTION);
520 glLoadIdentity();
521 gluPerspective(55.0, (float)sb->WIDTH / (float) sb->HEIGHT, 1.0, 300.0);
522
523 glMatrixMode(GL_MODELVIEW);
524
525 }
526
Draw(ModeInfo * mi)527 static void Draw(ModeInfo * mi)
528 {
529 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
530 int sphere;
531
532 mi->polygon_count = 0;
533
534 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
535
536 glPushMatrix();
537 glEnable(GL_DEPTH_TEST);
538
539 /* move eyes */
540 glTranslatef (-sb->eye[0], -sb->eye[1], -sb->eye[2]);
541
542 /* draw background */
543 if (do_texture)
544 {
545 glEnable(GL_LIGHTING);
546 glEnable(GL_TEXTURE_2D);
547 glColor3f(1, 1, 1);
548 #ifdef HAVE_GLBINDTEXTURE
549 glBindTexture(GL_TEXTURE_2D, sb->backid);
550 #endif /* HAVE_GLBINDTEXTURE */
551 }
552 else
553 {
554 glColor3f(0, 0, 0);
555 }
556 glBegin(GL_QUAD_STRIP);
557 #ifndef HAVE_MOBILE
558 /* Letterbox the background image */
559 glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(8, 4.1, -4);
560 glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(8, -4.1, -4);
561 glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-8, 4.1, -4);
562 glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-8, -4.1, -4);
563 #else
564 /* Fill the iPhone screen. Letterboxing looks dumb there. */
565 glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(4, 5.2, -4);
566 glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(4, -5.2, -4);
567 glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-4, 5.2, -4);
568 glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-4, -5.2, -4);
569 #endif
570 glEnd();
571 mi->polygon_count++;
572
573 gltrackball_rotate (sb->trackball);
574
575 /* rotate the balls */
576 glRotatef(sb->rotm[0], 1.0f, 0.0f, 0.0f);
577 glRotatef(sb->rotm[1], 0.0f, 1.0f, 0.0f);
578 glRotatef(sb->rotm[2], 0.0f, 0.0f, 1.0f);
579
580 if (! sb->button_down_p) {
581 sb->rotm[0] += sb->speed;
582 sb->rotm[1] += -(sb->speed);
583 sb->rotm[2] += 0;
584 }
585
586 /* draw the balls */
587 if (do_texture)
588 #ifdef HAVE_GLBINDTEXTURE
589 glBindTexture(GL_TEXTURE_2D, sb->faceid);
590 else
591 #endif /* HAVE_GLBINDTEXTURE */
592 glEnable(GL_LIGHTING);
593 for (sphere=0;sphere<spheres;sphere++)
594 {
595 drawSphere(mi,sphere);
596 }
597
598 glDisable(GL_TEXTURE_2D);
599 glDisable(GL_DEPTH_TEST);
600 glDisable(GL_LIGHTING);
601
602 /* manage framerate display */
603 if (MI_IS_FPS(mi)) do_fps (mi);
604 glPopMatrix();
605 }
606
607
Init(ModeInfo * mi)608 static void Init(ModeInfo * mi)
609 {
610 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
611 int i;
612
613 /* Default settings */
614 if (MI_IS_WIREFRAME(mi))
615 do_texture = False;
616 if (do_texture)
617 inittextures(mi);
618 else
619 {
620 sb->btexture = (XImage*) NULL;
621 sb->ftexture = (XImage*) NULL;
622 }
623
624 vinit(sb->eye ,0.0f, 0.0f, 6.0f);
625 vinit(sb->rotm ,0.0f, 0.0f, 0.0f);
626 sb->speed = MI_CYCLES(mi);
627
628 /* initialise object number */
629 object = object_arg-1;
630 if (object < 0 || object >= MAX_OBJ)
631 object = NRAND(MAX_OBJ);
632
633 /* initialise sphere number */
634 spheres = MI_COUNT(mi);
635 if (MI_COUNT(mi) > polygons[object].numverts)
636 spheres = polygons[object].numverts;
637 if (MI_COUNT(mi) < 1)
638 spheres = polygons[object].numverts;
639 /* initialise sphere radius */
640 for(i=0; i < spheres;i++)
641 {
642 #if RANDOM_RADIUS
643 sb->radius[i] = ((float) LRAND() / (float) MAXRAND);
644 if (sb->radius[i] < 0.3)
645 sb->radius[i] = 0.3;
646 if (sb->radius[i] > 0.7)
647 sb->radius[i] = 0.7;
648 #else
649 sb->radius[i] = polygons[object].radius;
650 #endif
651 }
652
653 if (MI_IS_DEBUG(mi)) {
654 (void) fprintf(stderr,
655 "%s:\n\tobject=%s\n\tspheres=%d\n\tspeed=%d\n\ttexture=%s\n",
656 MI_NAME(mi),
657 polygons[object].shortname,
658 spheres,
659 (int) MI_CYCLES(mi),
660 do_texture ? "on" : "off"
661 );
662 }
663
664 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
665 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
666 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
667 glEnable(GL_LIGHT1);
668 }
669
670 /*
671 *-----------------------------------------------------------------------------
672 *-----------------------------------------------------------------------------
673 * Xlock hooks.
674 *-----------------------------------------------------------------------------
675 *-----------------------------------------------------------------------------
676 */
677
678 /*
679 *-----------------------------------------------------------------------------
680 * Initialize sballs. Called each time the window changes.
681 *-----------------------------------------------------------------------------
682 */
683
init_sballs(ModeInfo * mi)684 ENTRYPOINT void init_sballs(ModeInfo * mi)
685 {
686 sballsstruct *sb;
687
688 MI_INIT(mi, sballs);
689 sb = &sballs[MI_SCREEN(mi)];
690
691 sb->trackball = gltrackball_init (True);
692
693 if ((sb->glx_context = init_GL(mi)) != NULL) {
694
695 #ifndef STANDALONE
696 Reshape(mi); /* xlock mode */
697 #else
698 reshape_sballs(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */
699 #endif
700 glDrawBuffer(GL_BACK);
701 Init(mi);
702
703 } else {
704 MI_CLEARWINDOW(mi);
705 }
706 }
707
708 /*
709 *-----------------------------------------------------------------------------
710 * Called by the mainline code periodically to update the display.
711 *-----------------------------------------------------------------------------
712 */
draw_sballs(ModeInfo * mi)713 ENTRYPOINT void draw_sballs(ModeInfo * mi)
714 {
715 Display *display = MI_DISPLAY(mi);
716 Window window = MI_WINDOW(mi);
717 sballsstruct *sb;
718
719 if (sballs == NULL)
720 return;
721 sb = &sballs[MI_SCREEN(mi)];
722
723 MI_IS_DRAWN(mi) = True;
724 if (!sb->glx_context)
725 return;
726
727 glXMakeCurrent(display, window, *sb->glx_context);
728 Draw(mi);
729 #ifndef STANDALONE
730 Reshape(mi); /* xlock mode */
731 #else
732 reshape_sballs(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */
733 #endif
734
735 glFinish();
736 glXSwapBuffers(display, window);
737 }
738
739
740 /*
741 *-----------------------------------------------------------------------------
742 * The display is being taken away from us. Free up malloc'ed
743 * memory and X resources that we've alloc'ed.
744 *-----------------------------------------------------------------------------
745 */
746
free_sballs(ModeInfo * mi)747 ENTRYPOINT void free_sballs(ModeInfo * mi)
748 {
749 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
750
751 if (!sb->glx_context) return;
752 glXMakeCurrent (MI_DISPLAY(mi), MI_WINDOW(mi), *sb->glx_context);
753
754 gltrackball_free (sb->trackball);
755
756 if (sb->btexture)
757 {
758 glDeleteTextures(1,&sb->backid);
759 XDestroyImage(sb->btexture);
760 sb->btexture = 0;
761 }
762 if (sb->ftexture)
763 {
764 glDeleteTextures(1,&sb->faceid);
765 XDestroyImage(sb->ftexture);
766 sb->ftexture = 0;
767 }
768 }
769
770 ENTRYPOINT Bool
sballs_handle_event(ModeInfo * mi,XEvent * event)771 sballs_handle_event (ModeInfo *mi, XEvent *event)
772 {
773 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
774
775 if (gltrackball_event_handler (event, sb->trackball,
776 MI_WIDTH (mi), MI_HEIGHT (mi),
777 &sb->button_down_p))
778 return True;
779
780 return False;
781 }
782
783
784 #ifndef STANDALONE
change_sballs(ModeInfo * mi)785 ENTRYPOINT void change_sballs(ModeInfo * mi)
786 {
787 sballsstruct *sb;
788
789 if (sballs == NULL)
790 return;
791 sb = &sballs[MI_SCREEN(mi)];
792
793 if (!sb->glx_context)
794 return;
795
796 /* initialise object number */
797 if ((object == 0) || (object > MAX_OBJ))
798 object = NRAND(MAX_OBJ-1)+1;
799 object--;
800
801 /* correct sphere number */
802 spheres = MI_COUNT(mi);
803 if (MI_COUNT(mi) > polygons[object].numverts)
804 spheres = polygons[object].numverts;
805 if (MI_COUNT(mi) < 1)
806 spheres = polygons[object].numverts;
807
808 if (MI_IS_DEBUG(mi)) {
809 (void) fprintf(stderr,
810 "%s:\n\tobject=%s\n\tspheres=%d\n\tspeed=%d\n\ttexture=%s\n",
811 MI_NAME(mi),
812 polygons[object].shortname,
813 spheres,
814 (int) MI_CYCLES(mi),
815 do_texture ? "on" : "off"
816 );
817 }
818 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *sb->glx_context);
819
820 }
821 #endif /* !STANDALONE */
822
823 XSCREENSAVER_MODULE ("SBalls", sballs)
824
825 #endif /* MODE_sballs */
826