1 /* sballs --- balls spinning like crazy in GL */
3 #if !defined( lint ) && !defined( SABER )
4 static const char sccsid[] = "@(#)sballs.c 5.02 2001/03/10 xlockmore";
7 /* Copyright (c) E. Lassauge, 2001. */
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.
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.
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/
26 * Eric Lassauge (November-07-2000) <lassauge@mail.dotcom.fr>
27 * http://lassauge.free.fr/linux.html
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
43 #ifdef STANDALONE /* xscreensaver mode */
44 #define PROGCLASS "Sballs"
45 #define HACK_INIT init_sballs
46 #define HACK_DRAW draw_sballs
47 #define HACK_RESHAPE reshape_sballs
48 #define sballs_opts xlockmore_opts
49 #define DEFAULTS "*delay: 10000 \n" \
53 "*trackmouse: False \n" \
54 "*showFPS: False \n" \
55 "*wireframe: False \n" \
59 #include "xlockmore.h" /* from the xscreensaver distribution */
60 #else /* !STANDALONE */
61 #include "xlock.h" /* from the xlockmore distribution */
63 #endif /* !STANDALONE */
67 #define MINSIZE 32 /* minimal viewport size */
68 #define FRAME 50 /* frame count interval */
69 #define MAX_OBJ 8 /* number of 3D objects */
75 #if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( HAVE_XPM )
76 /* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */
77 #include "xpm-ximage.h"
81 #include "../images/sball.xpm"
82 #include "../images/sball-bg.xpm"
83 #else /* !STANDALONE */
84 #include "pixmaps/sball.xpm"
85 #include "pixmaps/sball-bg.xpm"
86 #endif /* !STANDALONE */
89 /* Manage option vars */
90 #define DEF_TEXTURE "True"
91 #define DEF_TRACKMOUSE "False"
92 #define DEF_OBJECT "2"
93 #define DEF_OBJECT_INDX 2
94 static Bool do_texture;
95 static Bool do_trackmouse;
99 static XrmOptionDescRec opts[] = {
100 {(char *) "-texture", (char *) ".sballs.texture", XrmoptionNoArg, (caddr_t) "on"},
101 {(char *) "+texture", (char *) ".sballs.texture", XrmoptionNoArg, (caddr_t) "off"},
102 {(char *) "-trackmouse", (char *) ".sballs.trackmouse", XrmoptionNoArg, (caddr_t) "on"},
103 {(char *) "+trackmouse", (char *) ".sballs.trackmouse", XrmoptionNoArg, (caddr_t) "off"},
104 {(char *) "-object", (char *) ".sballs.object", XrmoptionSepArg, (caddr_t) NULL},
108 static argtype vars[] = {
109 {(caddr_t *) & do_texture, (char *) "texture", (char *) "Texture", (char *) DEF_TEXTURE, t_Bool},
110 {(caddr_t *) & do_trackmouse, (char *) "trackmouse", (char *) "TrackMouse", (char *) DEF_TRACKMOUSE, t_Bool},
111 {(caddr_t *) & object, (char *) "object", (char *) "Object", (char *) DEF_OBJECT, t_Int},
115 static OptionStruct desc[] = {
116 /*{(char *) "-count spheres", (char *) "set number of spheres"},*/
117 /*{(char *) "-cycles speed", (char *) "set ball speed value"},*/
118 {(char *) "-/+texture", (char *) "turn on/off texturing"},
119 {(char *) "-/+trackmouse", (char *) "turn on/off the tracking of the mouse"},
120 {(char *) "-object num", (char *) "number of the 3D object (0 means random)"},
123 ModeSpecOpt sballs_opts =
124 { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc };
127 ModStruct sballs_description =
128 { "sballs", "init_sballs", "draw_sballs", "release_sballs",
129 "draw_sballs", "change_sballs", (char *) NULL, &sballs_opts,
131 delay,count,cycles,size,ncolors,sat
133 10000, 0, 10, 400, 64, 1.0, "",
134 "balls spinning like crazy in GL", 0, NULL
136 #endif /* USE_MODULES */
138 /* misc types and defines */
139 #define vinit(a,i,j,k) {\
145 typedef vec_t vec3_t[3];
149 /* the mode struct, contains all per screen variables */
151 GLint WIDTH, HEIGHT; /* display dimensions */
152 GLXContext *glx_context;
155 XImage *btexture; /* back texture image bits */
156 XImage *ftexture; /* face texture image bits */
157 GLuint backid; /* back texture id: GL world */
158 GLuint faceid; /* face texture id: GL world */
164 float radius[MAX_BALLS];
168 /* array of sballsstruct indexed by screen number */
169 static sballsstruct *sballs = (sballsstruct *) NULL;
172 static float LightAmbient[]= { 1.0f, 1.0f, 1.0f, 1.0f };
173 static float LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
174 static float LightPosition[]= { 0.0f, 0.0f, 4.0f, 1.0f };
176 /* structure of the polyhedras */
178 const char *longname; /* long name of object */
179 const char *shortname; /* short name of object */
180 int numverts; /* number of vertices */
181 float radius; /* radius */
182 vec3_t v[MAX_BALLS];/* the vertices */
185 static Polyinfo polygons[] =
188 /* 0: objtetra - structure values for tetrahedron */
190 "tetrahedron", "tetra", /* long and short names */
191 4, /* number of vertices */
193 { /* vertices (x,y,z) */
194 /* all points must be within radius 2 of the origin */
204 /* 1: objcube - structure values for cube */
207 "hexahedron", "cube", /* long and short names */
208 8, /* number of vertices, edges, and faces */
210 { /* vertices (x,y,z) */
211 /* all points must be within radius 2 of the origin */
225 /* 2: objocta - structure values for octahedron */
228 "octahedron", "octa", /* long and short names */
229 6, /* number of vertices */
231 { /* vertices (x,y,z) */
232 /* all points must be within radius 2 of the origin */
243 /* 3: objdodec - structure values for dodecahedron */
246 "dodecahedron", "dodeca", /* long and short names */
247 20, /* number of vertices */
249 { /* vertices (x,y,z) */
250 /* all points must be within radius 2 of the origin */
251 {0.000000, 0.500000, 1.000000},
252 {0.000000, -0.500000, 1.000000},
253 {0.000000, -0.500000, -1.000000},
254 {0.000000, 0.500000, -1.000000},
255 {1.000000, 0.000000, 0.500000},
256 {-1.000000, 0.000000, 0.500000},
257 {-1.000000, 0.000000, -0.500000},
258 {1.000000, 0.000000, -0.500000},
259 {0.500000, 1.000000, 0.000000},
260 {-0.500000, 1.000000, 0.000000},
261 {-0.500000, -1.000000, 0.000000},
262 {0.500000, -1.000000, 0.000000},
263 {0.750000, 0.750000, 0.750000},
264 {-0.750000, 0.750000, 0.750000},
265 {-0.750000, -0.750000, 0.750000},
266 {0.750000, -0.750000, 0.750000},
267 {0.750000, -0.750000, -0.750000},
268 {0.750000, 0.750000, -0.750000},
269 {-0.750000, 0.750000, -0.750000},
270 {-0.750000, -0.750000, -0.750000},
274 /* 4: objicosa - structure values for icosahedron */
277 "icosahedron", "icosa", /* long and short names */
278 12, /* number of vertices */
280 { /* vertices (x,y,z) */
281 /* all points must be within radius 2 of the origin */
282 {0.00000000, 0.00000000, -0.95105650},
283 {0.00000000, 0.85065080, -0.42532537},
284 {0.80901698, 0.26286556, -0.42532537},
285 {0.50000000, -0.68819095, -0.42532537},
286 {-0.50000000, -0.68819095, -0.42532537},
287 {-0.80901698, 0.26286556, -0.42532537},
288 {0.50000000, 0.68819095, 0.42532537},
289 {0.80901698, -0.26286556, 0.42532537},
290 {0.00000000, -0.85065080, 0.42532537},
291 {-0.80901698, -0.26286556, 0.42532537},
292 {-0.50000000, 0.68819095, 0.42532537},
293 {0.00000000, 0.00000000, 0.95105650}
297 /* 5: objplane - structure values for plane */
300 "plane", "plane", /* long and short names */
301 4, /* number of vertices */
303 { /* vertices (x,y,z) */
304 /* all points must be within radius 2 of the origin */
314 /* 6: objpyr - structure values for pyramid */
317 "pyramid", "pyramid", /* long and short names */
318 5, /* number of vertices */
320 { /* vertices (x,y,z) */
321 /* all points must be within radius 1 of the origin */
332 /* 7: objstar - structure values for octahedron star (stellated octahedron?) */
334 "star", "star", /* long and short names */
335 8, /* number of vertices */
337 { /* vertices (x,y,z) */
338 /* all points must be within radius 1 of the origin */
358 *-----------------------------------------------------------------------------
359 *-----------------------------------------------------------------------------
361 *-----------------------------------------------------------------------------
362 *-----------------------------------------------------------------------------
365 static void clamp(vec3_t v)
369 for (i = 0; i < 3; i ++)
370 if (v[i] > 360 || v[i] < -360)
374 /* track the mouse in a joystick manner : not perfect but it works */
375 static void trackmouse(ModeInfo * mi)
377 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
378 /* we keep static values (not per screen) for the mouse stuff: in general you have only one mouse :-> */
379 static int max[2] = { 0, 0 };
380 static int min[2] = { 0x7fffffff, 0x7fffffff }, center[2];
385 (void) XQueryPointer(MI_DISPLAY(mi), MI_WINDOW(mi),
386 &r, &c, &rx, &ry, &cx, &cy, &m);
392 center[0] = (max[0] + min[0]) / 2;
398 center[1] = (max[1] + min[1]) / 2;
400 if (fabs(center[0] - (float) cx) > 0.1 * (max[0] - min[0]))
401 sb->rot[0] -= ((center[0] - (float) cx) / (max[0] - min[0]) * 180.0f) / 200.0f;
402 if (fabs(center[1] - (float) cy) > 0.1 * (max[1] - min[1]))
403 sb->rot[1] -= ((center[1] - (float) cy) / (max[1] - min[1]) * 180.0f) / 200.0f;;
406 /* oops: can't get those buttons */
414 /* initialise textures */
415 static void inittextures(ModeInfo * mi)
417 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
419 #if defined( I_HAVE_XPM )
422 glGenTextures(1, &sb->backid);
423 #ifdef HAVE_GLBINDTEXTURE
424 glBindTexture(GL_TEXTURE_2D, sb->backid);
425 #endif /* HAVE_GLBINDTEXTURE */
427 sb->btexture = xpm_to_ximage(MI_DISPLAY(mi),
431 if (!(sb->btexture)) {
432 (void) fprintf(stderr, "Error reading the background texture.\n");
433 glDeleteTextures(1, &sb->backid);
435 sb->faceid = 0; /* default textures */
440 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
442 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
443 sb->btexture->width, sb->btexture->height, 0,
445 /* GL_UNSIGNED_BYTE, */
446 GL_UNSIGNED_INT_8_8_8_8_REV,
448 check_gl_error("texture");
450 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
451 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
454 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
456 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
458 glGenTextures(1, &sb->faceid);
459 #ifdef HAVE_GLBINDTEXTURE
460 glBindTexture(GL_TEXTURE_2D, sb->faceid);
461 #endif /* HAVE_GLBINDTEXTURE */
463 sb->ftexture = xpm_to_ximage(MI_DISPLAY(mi),
467 if (!(sb->ftexture)) {
468 (void) fprintf(stderr, "Error reading the face texture.\n");
469 glDeleteTextures(1, &sb->faceid);
474 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
476 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
477 sb->ftexture->width, sb->ftexture->height, 0,
479 /* GL_UNSIGNED_BYTE, */
480 GL_UNSIGNED_INT_8_8_8_8_REV,
482 check_gl_error("texture");
484 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
485 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
487 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
490 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
494 sb->faceid = 0; /* default textures */
497 #else /* !I_HAVE_XPM */
499 sb->faceid = 0; /* default textures */
501 #endif /* !I_HAVE_XPM */
504 static void drawSphere(ModeInfo * mi,int sphere_num)
506 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
507 float x = polygons[object].v[sphere_num][0];
508 float y = polygons[object].v[sphere_num][1];
509 float z = polygons[object].v[sphere_num][2];
512 float radius = sb->radius[sphere_num];
513 double majorStep = (M_PI / numMajor);
514 double minorStep = (2.0 * M_PI / numMinor);
518 glTranslatef(x, y, z);
520 glColor4f(1, 1, 1, 1);
521 for (i = 0; i < numMajor; ++i)
523 double a = i * majorStep;
524 double b = a + majorStep;
525 double r0 = radius * sin(a);
526 double r1 = radius * sin(b);
527 GLfloat z0 = radius * cos(a);
528 GLfloat z1 = radius * cos(b);
530 glBegin(MI_IS_WIREFRAME(mi) ? GL_LINE_STRIP: GL_TRIANGLE_STRIP);
531 for (j = 0; j <= numMinor; ++j)
533 double c = j * minorStep;
537 glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
538 glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
539 glVertex3f(x * r0, y * r0, z0);
541 glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
542 glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
543 glVertex3f(x * r1, y * r1, z1);
552 *-----------------------------------------------------------------------------
553 *-----------------------------------------------------------------------------
555 *-----------------------------------------------------------------------------
556 *-----------------------------------------------------------------------------
560 static void Reshape(ModeInfo * mi)
562 void reshape_sballs(ModeInfo * mi, int width, int height)
566 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
567 int size = MI_SIZE(mi);
569 /* Viewport is specified size if size >= MINSIZE && size < screensize */
571 sb->WIDTH = MI_WIDTH(mi);
572 sb->HEIGHT = MI_HEIGHT(mi);
573 } else if (size < MINSIZE) {
575 sb->HEIGHT = MINSIZE;
577 sb->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
578 sb->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
580 glViewport((MI_WIDTH(mi) - sb->WIDTH) / 2, (MI_HEIGHT(mi) - sb->HEIGHT) / 2, sb->WIDTH, sb->HEIGHT);
581 glMatrixMode(GL_PROJECTION);
583 gluPerspective(55.0, (float)sb->WIDTH / (float) sb->HEIGHT, 1.0, 300.0);
585 glMatrixMode(GL_MODELVIEW);
589 static void Draw(ModeInfo * mi)
591 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
594 if (do_trackmouse && !MI_IS_ICONIC(mi))
597 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
600 glEnable(GL_DEPTH_TEST);
603 glTranslatef (-sb->eye[0], -sb->eye[1], -sb->eye[2]);
605 /* draw background */
608 glEnable(GL_LIGHTING);
609 glEnable(GL_TEXTURE_2D);
611 #ifdef HAVE_GLBINDTEXTURE
612 glBindTexture(GL_TEXTURE_2D, sb->backid);
613 #endif /* HAVE_GLBINDTEXTURE */
619 glBegin(GL_QUAD_STRIP);
620 glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(8, 4.1, -4);
621 glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(8, -4.1, -4);
622 glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-8, 4.1, -4);
623 glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-8, -4.1, -4);
626 /* rotate the mouse */
627 glRotatef(sb->rot[0], 1.0f, 0.0f, 0.0f);
628 glRotatef(sb->rot[1], 0.0f, 1.0f, 0.0f);
629 glRotatef(sb->rot[2], 0.0f, 0.0f, 1.0f);
631 /* rotate the balls */
632 glRotatef(sb->rotm[0], 1.0f, 0.0f, 0.0f);
633 glRotatef(sb->rotm[1], 0.0f, 1.0f, 0.0f);
634 glRotatef(sb->rotm[2], 0.0f, 0.0f, 1.0f);
636 sb->rotm[0] += sb->speed;
637 sb->rotm[1] += -(sb->speed);
642 #ifdef HAVE_GLBINDTEXTURE
643 glBindTexture(GL_TEXTURE_2D, sb->faceid);
644 #endif /* HAVE_GLBINDTEXTURE */
646 glEnable(GL_LIGHTING);
647 for (sphere=0;sphere<spheres;sphere++)
649 drawSphere(mi,sphere);
652 glDisable(GL_TEXTURE_2D);
653 glDisable(GL_DEPTH_TEST);
654 glDisable(GL_LIGHTING);
656 /* manage framerate display */
657 if (MI_IS_FPS(mi)) do_fps (mi);
662 static void Init(ModeInfo * mi)
664 sballsstruct *sb = &sballs[MI_SCREEN(mi)];
667 /* Default settings */
668 if (MI_IS_WIREFRAME(mi))
674 sb->btexture = (XImage*) NULL;
675 sb->ftexture = (XImage*) NULL;
678 vinit(sb->eye ,0.0f, 0.0f, 6.0f);
679 vinit(sb->rot ,0.0f, 0.0f, 0.0f);
680 vinit(sb->rotm ,0.0f, 0.0f, 0.0f);
681 sb->speed = MI_CYCLES(mi);
683 /* initialise object number */
685 object = NRAND(MAX_OBJ);
686 if ((object == 0) || (object > MAX_OBJ))
687 object = DEF_OBJECT_INDX;
690 /* initialise sphere number */
691 spheres = MI_COUNT(mi);
692 if (MI_COUNT(mi) > polygons[object].numverts)
693 spheres = polygons[object].numverts;
694 if (MI_COUNT(mi) < 1)
695 spheres = polygons[object].numverts;
696 /* initialise sphere radius */
697 for(i=0; i < spheres;i++)
700 sb->radius[i] = ((float) LRAND() / (float) MAXRAND);
701 if (sb->radius[i] < 0.3)
703 if (sb->radius[i] > 0.7)
706 sb->radius[i] = polygons[object].radius;
710 if (MI_IS_DEBUG(mi)) {
711 (void) fprintf(stderr,
712 "%s:\n\tobject=%s\n\tspheres=%d\n\tspeed=%d\n\ttexture=%s\n",
714 polygons[object].shortname,
717 do_texture ? "on" : "off"
721 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
722 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
723 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
726 glClearColor(0, 0, 0, 0);
730 *-----------------------------------------------------------------------------
731 *-----------------------------------------------------------------------------
733 *-----------------------------------------------------------------------------
734 *-----------------------------------------------------------------------------
738 *-----------------------------------------------------------------------------
739 * Initialize sballs. Called each time the window changes.
740 *-----------------------------------------------------------------------------
743 void init_sballs(ModeInfo * mi)
747 if (sballs == NULL) {
748 if ((sballs = (sballsstruct *) calloc(MI_NUM_SCREENS(mi),
749 sizeof(sballsstruct))) == NULL)
752 sb = &sballs[MI_SCREEN(mi)];
754 if ((sb->glx_context = init_GL(mi)) != NULL) {
757 Reshape(mi); /* xlock mode */
759 reshape_sballs(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */
761 glDrawBuffer(GL_BACK);
770 *-----------------------------------------------------------------------------
771 * Called by the mainline code periodically to update the display.
772 *-----------------------------------------------------------------------------
774 void draw_sballs(ModeInfo * mi)
776 Display *display = MI_DISPLAY(mi);
777 Window window = MI_WINDOW(mi);
782 sb = &sballs[MI_SCREEN(mi)];
784 MI_IS_DRAWN(mi) = True;
785 if (!sb->glx_context)
788 glXMakeCurrent(display, window, *(sb->glx_context));
791 Reshape(mi); /* xlock mode */
793 reshape_sballs(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */
797 glXSwapBuffers(display, window);
802 *-----------------------------------------------------------------------------
803 * The display is being taken away from us. Free up malloc'ed
804 * memory and X resources that we've alloc'ed. Only called
805 * once, we must zap everything for every screen.
806 *-----------------------------------------------------------------------------
809 void release_sballs(ModeInfo * mi)
813 if (sballs != NULL) {
814 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
815 sballsstruct *sb = &sballs[screen];
818 glDeleteTextures(1,&sb->backid);
819 XDestroyImage(sb->btexture);
823 glDeleteTextures(1,&sb->faceid);
824 XDestroyImage(sb->ftexture);
827 (void) free((void *) sballs);
828 sballs = (sballsstruct *) NULL;
833 void change_sballs(ModeInfo * mi)
839 sb = &sballs[MI_SCREEN(mi)];
841 if (!sb->glx_context)
844 /* initialise object number */
846 object = NRAND(MAX_OBJ);
847 if ((object == 0) || (object > MAX_OBJ))
848 object = DEF_OBJECT_INDX;
851 /* correct sphere number */
852 spheres = MI_COUNT(mi);
853 if (MI_COUNT(mi) > polygons[object].numverts)
854 spheres = polygons[object].numverts;
855 if (MI_COUNT(mi) < 1)
856 spheres = polygons[object].numverts;
858 if (MI_IS_DEBUG(mi)) {
859 (void) fprintf(stderr,
860 "%s:\n\tobject=%s\n\tspheres=%d\n\tspeed=%d\n\ttexture=%s\n",
862 polygons[object].shortname,
865 do_texture ? "on" : "off"
868 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sb->glx_context));
871 #endif /* MODE_sballs */