1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* glplanet --- 3D rotating planet, e.g., Earth. */
3
4 #if 0
5 static const char sccsid[] = "@(#)glplanet.c 5.01 01/04/13 xlockmore";
6 #endif
7
8 /*-
9 * Permission to use, copy, modify, and distribute this software and its
10 * documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appear in all copies and that
12 * both that copyright notice and this permission notice appear in
13 * supporting documentation.
14 *
15 * This file is provided AS IS with no warranties of any kind. The author
16 * shall have no liability with respect to the infringement of copyrights,
17 * trade secrets or any patents by this file or any part thereof. In no
18 * event will the author be liable for any lost revenue or profits or
19 * other special, indirect and consequential damages.
20 *
21 * Revision History:
22 *
23 * 13-Apr-01: rolf@groppe.de Did this on the xlockmore version
24 * (21-Mar-01: jwz AT jwz.org Broke sphere routine out into its own file.
25 * Done on the xscreensaver version)
26 *
27 * 5-Apr-01: rolf@groppe.de Ported this mode from xscreensaver to xlock.
28 * Made smoother roll & rotational movement
29 * configurable by -count and -cycles.
30 * Renamed the parameter -image to -pimage
31 *
32 * 9-Oct-98: dek@cgl.ucsf.edu Added stars.
33 *
34 * 8-Oct-98: jwz AT jwz.org Made the 512x512x1 xearth image be built in.
35 * Made it possible to load XPM or XBM files.
36 * Made the planet bounce and roll around.
37 *
38 * 8-Oct-98: Released initial version of "glplanet"
39 * (David Konerding, dek@cgl.ucsf.edu)
40 *
41 * BUGS:
42 * -bounce is broken
43 *
44 * For even more spectacular results, grab the images from the "SSysten"
45 * package (http://www.msu.edu/user/kamelkev/) and do this:
46 *
47 * cd ssystem-1.4/hires/
48 * foreach f ( *.jpg )
49 * djpeg $f | ppmquant 254 | ppmtoxpm > /tmp/$f:r.xpm
50 * end
51 *
52 * cd /tmp
53 * foreach f ( *.xpm )
54 * xlock -mode glplanet -pimage $f
55 * end
56 */
57
58
59 #ifdef VMS
60 #include <types.h>
61 #endif
62
63 #ifdef STANDALONE
64 # define MODE_glplanet
65 #define DEFAULTS "*delay: 15000 \n" \
66 "*showFPS: False \n" \
67 "*wireframe: False \n" \
68 "*imageForeground: Green \n" \
69 "*imageBackground: Blue \n"
70
71 #define free_glplanet 0
72 #define glplanet_handle_event 0
73 # include "xlockmore.h" /* from the xscreensaver distribution */
74 #else /* !STANDALONE */
75 # include "xlock.h" /* from the xlockmore distribution */
76 # include "visgl.h"
77 #endif /* !STANDALONE */
78
79 #ifdef MODE_glplanet /* whole file */
80
81 #ifdef HAVE_XPM
82 #include <X11/xpm.h>
83 # ifndef PIXEL_ALREADY_TYPEDEFED
84 # define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
85 # endif
86 #endif
87
88 #ifdef USE_XMU
89 # ifdef VMS
90 # include <Xmu/Drawing.h>
91 #else /* !VMS */
92 # include <X11/Xmu/Drawing.h>
93 # endif /* !VMS */
94 #endif
95
96 #include "sphere.h"
97
98 #include <GL/glu.h>
99
100 #define DEF_ROTATE "True"
101 #define DEF_ROLL "True"
102 #define DEF_BOUNCE "True"
103 #define DEF_TEXTURE "True"
104 #define DEF_STARS "True"
105 #define DEF_LIGHT "True"
106 #define DEF_IMAGE "BUILTIN"
107 #define MINROLL 1
108 #define MINROT 2
109
110 #undef countof
111 #define countof(x) (sizeof((x))/sizeof((*x)))
112
113 static int do_rotate;
114 static int do_roll;
115 static int do_bounce;
116 static int do_texture;
117 static int do_stars;
118 static int do_light;
119 static char *which_image;
120 static XrmOptionDescRec opts[] = {
121 {(char *) "-rotate", (char *) ".glplanet.rotate", XrmoptionNoArg, (caddr_t) "on" },
122 {(char *) "+rotate", (char *) ".glplanet.rotate", XrmoptionNoArg, (caddr_t) "off" },
123 {(char *) "-roll", (char *) ".glplanet.roll", XrmoptionNoArg, (caddr_t) "on" },
124 {(char *) "+roll", (char *) ".glplanet.roll", XrmoptionNoArg, (caddr_t) "off" },
125 {(char *) "-bounce", (char *) ".glplanet.bounce", XrmoptionNoArg, (caddr_t) "on" },
126 {(char *) "+bounce", (char *) ".glplanet.bounce", XrmoptionNoArg, (caddr_t) "off" },
127 {(char *) "-texture", (char *) ".glplanet.texture", XrmoptionNoArg, (caddr_t) "on" },
128 {(char *) "+texture", (char *) ".glplanet.texture", XrmoptionNoArg, (caddr_t) "off" },
129 {(char *) "-stars", (char *) ".glplanet.stars", XrmoptionNoArg, (caddr_t) "on" },
130 {(char *) "+stars", (char *) ".glplanet.stars", XrmoptionNoArg, (caddr_t) "off" },
131 {(char *) "-light", (char *) ".glplanet.light", XrmoptionNoArg, (caddr_t) "on" },
132 {(char *) "+light", (char *) ".glplanet.light", XrmoptionNoArg, (caddr_t) "off" },
133 {(char *) "-pimage", (char *) ".glplanet.pimage", XrmoptionSepArg, (caddr_t) 0 }
134 };
135
136 static argtype vars[] = {
137 {(void *) &do_rotate, (char *) "rotate", (char *) "Rotate",
138 (char *) DEF_ROTATE, t_Bool},
139 {(void *) &do_roll, (char *) "roll", (char *) "Roll",
140 (char *) DEF_ROLL, t_Bool},
141 {(void *) &do_bounce, (char *) "bounce", (char *) "Bounce",
142 (char *) DEF_BOUNCE, t_Bool},
143 {(void *) &do_texture, (char *) "texture", (char *) "Texture",
144 (char *) DEF_TEXTURE, t_Bool},
145 {(void *) &do_stars, (char *) "stars", (char *) "Stars",
146 (char *) DEF_STARS, t_Bool},
147 {(void *) &do_light, (char *) "light", (char *) "Light",
148 (char *) DEF_LIGHT, t_Bool},
149 {(void *) &which_image, (char *) "pimage", (char *) "Pimage",
150 (char *) DEF_IMAGE, t_String},
151 };
152
153 static OptionStruct desc[] = {
154 {(char *) "-/+rotate", (char *) "turn on/off rotatation"},
155 {(char *) "-/+roll", (char *) "turn on/off rolling"},
156 {(char *) "-/+bounce", (char *) "turn on/off bouncing"},
157 {(char *) "-/+texture", (char *) "turn on/off texture mapping"},
158 {(char *) "-/+stars", (char *) "turn on/off stars"},
159 {(char *) "-/+light", (char *) "turn on/off light source"},
160 {(char *) "-pimage", (char *) "set image"},
161 };
162
163 ENTRYPOINT ModeSpecOpt glplanet_opts =
164 {countof(opts), opts, countof(vars), vars, desc};
165
166 #ifdef USE_MODULES
167 ModStruct glplanet_description =
168 {"glplanet", "init_glplanet", "draw_glplanet", "release_glplanet",
169 "draw_glplanet", "init_glplanet", (char *) NULL, &glplanet_opts,
170 15000, 1, 2, 1, 64, 1.0, "",
171 "Animates texture mapped sphere (planet)", 0, NULL};
172 #endif
173
174 #define FLOATRAND(a) (((double)LRAND() / (double)MAXRAND) * a)
175
176 #include "bitmaps/earth.xbm"
177 #include "xpm-ximage.h"
178
179
180 /*-
181 * slices and stacks are used in the sphere parameterization routine.
182 * more slices and stacks will increase the quality of the sphere,
183 * at the expense of rendering speed
184 */
185
186 #define NUM_STARS 1000
187 #define SLICES 32
188 #define STACKS 32
189
190 /* radius of the sphere- fairly arbitrary */
191 #define RADIUS 4
192
193 /* distance away from the sphere model */
194 #define DIST 40
195
196
197
198 /* structure for holding the planet data */
199 typedef struct {
200 #ifdef WIN32
201 HGLRC glx_context;
202 #else
203 GLXContext *glx_context;
204 #endif
205 Window window;
206 GLuint platelist;
207 GLuint starlist;
208 int screen_width, screen_height;
209
210 XColor fg, bg;
211
212 GLfloat tx, ty, tz;
213 GLfloat dtx, dty, dtz;
214 GLfloat xpos, ypos, zpos;
215 GLfloat dx, dy, dz;
216 GLfloat box_width, box_height, box_depth;
217 int roll_div, rot_div;
218
219 } planetstruct;
220
221
222 static planetstruct *planets = (planetstruct *) NULL;
223
224 #if 0
225 static inline void
226 normalize(GLfloat v[3])
227 {
228 GLfloat d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
229
230 if (d != 0) {
231 v[0] /= d;
232 v[1] /= d;
233 v[2] /= d;
234 } else {
235 v[0] = v[1] = v[2] = 0;
236 }
237 }
238 #endif
239
240 /* Set up and enable texturing on our object */
241 static Bool
setup_xbm_texture(unsigned char * bits,int width,int height,XColor * fgc,XColor * bgc)242 setup_xbm_texture (unsigned char *bits, int width, int height,
243 XColor *fgc, XColor *bgc)
244 {
245 unsigned int fg = (((fgc->red >> 8) << 16) |
246 ((fgc->green >> 8) << 8) |
247 ((fgc->blue >> 8)));
248 unsigned int bg = (((bgc->red >> 8) << 16) |
249 ((bgc->green >> 8) << 8) |
250 ((bgc->blue >> 8)));
251
252 unsigned char *data = (unsigned char *)
253 malloc ((width * height * 24) / 8);
254 unsigned char *out = data;
255 int x, y;
256
257 for (y = 0; y < height; y++)
258 for (x = 0; x < width; x++)
259 {
260 unsigned char byte = bits [(y * (width / 8) + (x / 8))];
261 unsigned char bit = (byte & (1 << (x % 8))) >> (x % 8);
262 unsigned int word = (bit ? bg : fg);
263 *out++ = (word & 0xFF0000) >> 16;
264 *out++ = (word & 0x00FF00) >> 8;
265 *out++ = (word & 0x0000FF);
266 }
267
268 clear_gl_error();
269 glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0,
270 GL_RGB, GL_UNSIGNED_BYTE, data);
271 #ifndef STANDALONE
272 if (check_gl_error("texture")) {
273 if (data != NULL) {
274 free(data);
275 }
276 return False;
277 }
278 #endif
279
280 /* setup parameters for texturing */
281 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
282 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
283 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
284 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
285 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
286 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
287
288 if (data != NULL) {
289 free(data);
290 }
291 return True;
292 }
293
294
295 static Bool
setup_file_texture(ModeInfo * mi,char * filename)296 setup_file_texture (ModeInfo *mi, char *filename)
297 {
298 #ifdef HAVE_XPM
299 {
300 char **xpm_data = 0;
301 int result = XpmReadFileToData (filename, &xpm_data);
302 switch (result) {
303 case XpmSuccess:
304 {
305 XImage *image = xpm_to_ximage (MI_DISPLAY(mi), MI_VISUAL(mi),
306 MI_COLORMAP(mi), xpm_data);
307
308 clear_gl_error();
309 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
310 image->width, image->height, 0,
311 GL_RGBA, GL_UNSIGNED_BYTE, image->data);
312 #ifdef STANDALONE
313 check_gl_error("texture A");
314 #else
315 if (check_gl_error("texture A")) {
316 return False;
317 }
318 #endif
319 /* setup parameters for texturing */
320 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
321 glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
322
323 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
324 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
325 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
326 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
327 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
328 return True;
329 }
330
331 case XpmOpenFailed:
332 (void) fprintf (stderr, "Glplanet: file %s doesn't exist.\n", filename);
333 return False;
334
335 case XpmFileInvalid:
336 /* Fall through and try it as an XBM. */
337 break;
338
339 case XpmNoMemory:
340 (void) fprintf (stderr, "Glplanet: XPM: out of memory\n");
341 return False;
342
343 default:
344 (void) fprintf (stderr, "Glplanet: XPM: unknown error code %d\n", result);
345 return False;
346 }
347 }
348 #endif /* HAVE_XPM */
349
350 #ifdef USE_XMU
351 {
352 planetstruct *gp = &planets[MI_SCREEN(mi)];
353 unsigned int width = 0;
354 unsigned int height = 0;
355 unsigned char *data = 0;
356 int xhot, yhot;
357 int status = XmuReadBitmapDataFromFile (filename, &width, &height, &data,
358 &xhot, &yhot);
359 if (status != Success)
360 {
361 #ifdef HAVE_XPM
362 (void) fprintf (stderr, "Glplanet: not an XPM file: %s\n", filename);
363 # endif
364 (void) fprintf (stderr, "Glplanet: not an XBM file: %s\n", filename);
365 return False;
366 }
367
368 if (!setup_xbm_texture ((unsigned char *) data, width, height,
369 &gp->fg, &gp->bg))
370 return False;
371 }
372 return True;
373 #else /* !XMU */
374
375 #ifdef HAVE_XPM
376 (void) fprintf (stderr, "Glplanet: not an XPM file: %s\n", filename);
377 # endif
378 (void) fprintf (stderr, "Glplanet: your vendor doesn't ship the standard Xmu library.\n");
379 (void) fprintf (stderr, "Glplanet: we can't load XBM files without it.\n");
380 return False;
381 #endif /* !XMU */
382 }
383
384
385 static Bool
setup_texture(ModeInfo * mi)386 setup_texture(ModeInfo * mi)
387 {
388 planetstruct *gp = &planets[MI_SCREEN(mi)];
389 if (!which_image ||
390 !*which_image ||
391 !strcmp(which_image, "BUILTIN")) {
392 if (!setup_xbm_texture (earth_bits, earth_width, earth_height,
393 &gp->fg, &gp->bg))
394 return False;
395
396 } else {
397 if (!setup_file_texture (mi, which_image))
398 return False;
399 }
400 return True;
401 }
402
403
404 /* Set up and enable lighting */
405 static void
setup_light(void)406 setup_light(void)
407 {
408 /* set a number of parameters which make the scene look much nicer */
409 glEnable(GL_BLEND);
410 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
411 glShadeModel(GL_SMOOTH);
412 }
413
414
415 /* Set up and enable face culling so we don't see the inside of the sphere */
416 static void
setup_face(void)417 setup_face(void)
418 {
419 glEnable(GL_CULL_FACE);
420 glCullFace(GL_BACK);
421 }
422
423 /* lame way to generate some random stars */
424 static void
generate_stars(ModeInfo * mi,int width,int height)425 generate_stars(ModeInfo * mi, int width, int height)
426 {
427 int i;
428 /* GLfloat size_range[2], size;*/
429 GLfloat x, y;
430
431 planetstruct *gp = &planets[MI_SCREEN(mi)];
432
433 /* glGetFloatv(GL_POINT_SIZE_RANGE, size_range); */
434
435 /* (void) printf("size range: %f\t%f\n", size_range[0], size_range[1]); */
436 gp->starlist = glGenLists(1);
437 glNewList(gp->starlist, GL_COMPILE);
438
439 /* this hackery makes the viewport map one-to-one with Vertex arguments */
440 glMatrixMode(GL_PROJECTION);
441 glPushMatrix();
442 glMatrixMode(GL_PROJECTION);
443 glLoadIdentity();
444 gluOrtho2D(0, width, 0, height);
445 glMatrixMode(GL_MODELVIEW);
446 glLoadIdentity();
447
448 /* disable depth testing for the stars, so they don't obscure the planet */
449 glDisable(GL_DEPTH_TEST);
450 glEnable(GL_POINT_SMOOTH);
451 glEnable(GL_BLEND);
452 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
453
454 glBegin(GL_POINTS);
455 for(i = 0 ; i < NUM_STARS ; i++)
456 {
457 /* size = ((random()%size_range[0])) * size_range[1]/2.; */
458 /* glPointSize(size); */
459 x = random() % width;
460 y = random() % height;
461 glVertex2f(x,y);
462 }
463 glEnd();
464
465 /* return to original PROJECT and MODELVIEW */
466 glMatrixMode(GL_PROJECTION);
467 glPopMatrix();
468 glMatrixMode(GL_MODELVIEW);
469
470
471 glEndList();
472
473 }
474
475 /* Initialization function for screen saver */
476 static void
pinit(ModeInfo * mi)477 pinit(ModeInfo * mi)
478 {
479 Bool wire = MI_IS_WIREFRAME(mi);
480 planetstruct *gp = &planets[MI_SCREEN(mi)];
481
482 if (wire) {
483 glEnable(GL_LINE_SMOOTH);
484 do_texture = False;
485 }
486
487 /* turn on various options we like */
488 if (do_texture) {
489 if (!setup_texture(mi))
490 do_texture = False;
491 }
492 if (do_light)
493 setup_light();
494
495 setup_face();
496
497 if (do_stars) {
498 glEnable(GL_POINT_SMOOTH);
499 generate_stars(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
500 }
501
502 gp->platelist=glGenLists(1);
503 glNewList(gp->platelist, GL_COMPILE);
504 glPushMatrix ();
505 glScalef (RADIUS, RADIUS, RADIUS);
506 unit_sphere (STACKS, SLICES, wire);
507 glPopMatrix ();
508 glEndList();
509 }
510
511 static void
draw_sphere_glp(ModeInfo * mi)512 draw_sphere_glp(ModeInfo * mi)
513 {
514 planetstruct *gp = &planets[MI_SCREEN(mi)];
515
516 glEnable(GL_DEPTH_TEST);
517
518 /* turn on the various attributes for making the sphere look nice */
519 if (do_texture)
520 glEnable(GL_TEXTURE_2D);
521
522 if (do_light)
523 {
524 glEnable(GL_LIGHTING);
525 glEnable(GL_LIGHT0);
526 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
527 glEnable(GL_COLOR_MATERIAL);
528 }
529
530 glCallList(gp->platelist);
531
532 }
533
534
535 #define RANDSIGN() ((random() & 1) ? 1 : -1)
536
537 static void
pick_velocity(ModeInfo * mi)538 pick_velocity (ModeInfo * mi)
539 {
540 float roll1,roll2,rot1,rot2;
541 planetstruct *gp = &planets[MI_SCREEN(mi)];
542
543 gp->roll_div = MI_COUNT(mi);
544 if (gp->roll_div <= MINROLL) gp->roll_div = MINROLL * 10;
545 gp->rot_div = MI_CYCLES(mi);
546 if (gp->rot_div <= MINROT) gp->rot_div = MINROT * 50;
547
548 roll1 = gp->roll_div / 100.0;
549 roll2 = roll1 * 0.75;
550 rot1 = gp->rot_div / 100.0;
551 rot2 = rot1;
552 gp->box_width = 15.0;
553 gp->box_height = 15.0;
554 gp->box_depth = 5.0;
555
556 gp->tx = 0.0;
557 gp->ty = 0.0;
558 gp->tz = FLOATRAND(360);
559
560 /* following values changed for smoother rotation */
561 gp->dtx = (FLOATRAND(roll1) + FLOATRAND(roll2)) * RANDSIGN();
562 gp->dty = (FLOATRAND(roll1) + FLOATRAND(roll2)) * RANDSIGN();
563 gp->dtz = (FLOATRAND(rot1) + FLOATRAND(rot2)); /* the sun sets in the west */
564
565 /* following values are unused
566 gp->dx = (FLOATRAND(0.2) + FLOATRAND(0.2)) * RANDSIGN();
567 gp->dy = (FLOATRAND(0.2) + FLOATRAND(0.2)) * RANDSIGN();
568 gp->dz = (FLOATRAND(0.2) + FLOATRAND(0.2)) * RANDSIGN(); */
569 }
570
571
572 static void
rotate_and_move(ModeInfo * mi)573 rotate_and_move (ModeInfo * mi)
574 {
575 planetstruct *gp = &planets[MI_SCREEN(mi)];
576
577 if (do_roll)
578 {
579 gp->tx += gp->dtx;
580 while (gp->tx < 0) gp->tx += 360;
581 while (gp->tx > 360) gp->tx -= 360;
582
583 gp->ty += gp->dty;
584 while (gp->ty < 0) gp->ty += 360;
585 while (gp->ty > 360) gp->ty -= 360;
586 }
587
588 if (do_rotate)
589 {
590 gp->tz += gp->dtz;
591 while (gp->tz < 0) gp->tz += 360;
592 while (gp->tz > 360) gp->tz -= 360;
593 }
594
595 if (do_bounce)
596 {
597 static int frame = 0;
598 /*
599 # define SINOID(SCALE,SIZE) \
600 ((((1 + sin((frame * (SCALE)) / 16 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
601 gp->xpos = SINOID(0.031, gp->box_width);
602 gp->ypos = SINOID(0.023, gp->box_height);
603 gp->zpos = SINOID(0.017, gp->box_depth);
604 frame++;
605 */
606 /* Original function replaced for faster execution */
607 # define SINOID(SCALE,SIZE) \
608 (sin(frame * (SCALE)) / 2.0) * (SIZE)
609 gp->xpos = SINOID(0.006086836, gp->box_width);
610 gp->ypos = SINOID(0.004516039, gp->box_height);
611 gp->zpos = SINOID(0.003337942, gp->box_depth);
612 frame++;
613
614 }
615 }
616
617
618 /* Standard reshape function */
619 static void
reshape_glplanet(ModeInfo * mi,int width,int height)620 reshape_glplanet(ModeInfo *mi, int width, int height)
621 {
622 GLfloat light[4];
623 GLfloat h = (GLfloat) height / (GLfloat) width;
624
625 light[0] = -1;
626 light[1] = (int) (((random() % 3) & 0xFF) - 1);
627 light[2] = (int) (((random() % 3) & 0xFF) - 1);
628 light[3] = 0;
629
630 glViewport(0, 0, (GLint) width, (GLint) height);
631 glMatrixMode(GL_PROJECTION);
632 glLoadIdentity();
633 glFrustum(-1.0, 1.0, -h, h, 5.0, 100.0);
634 glMatrixMode(GL_MODELVIEW);
635 glLoadIdentity();
636 glTranslatef(0.0, 0.0, -DIST);
637 glLightfv(GL_LIGHT0, GL_POSITION, light);
638 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
639
640 }
641
642
643 ENTRYPOINT void
init_glplanet(ModeInfo * mi)644 init_glplanet(ModeInfo * mi)
645 {
646 int screen = MI_SCREEN(mi);
647
648 planetstruct *gp;
649
650 MI_INIT(mi, planets);
651 gp = &planets[screen];
652
653 pick_velocity (mi);
654
655 {
656 /* char *f = get_string_resource("imageForeground", "Foreground");
657 char *b = get_string_resource("imageBackground", "Background"); */
658 char *f = (char *) strdup("Green");
659 char *b = (char *) strdup("Blue");
660 char *s;
661 if (!f) f = (char *) strdup("white");
662 if (!b) b = (char *) strdup("black");
663
664 for (s = f + strlen(f)-1; s > f; s--)
665 if (*s == ' ' || *s == '\t')
666 *s = 0;
667 for (s = b + strlen(b)-1; s > b; s--)
668 if (*s == ' ' || *s == '\t')
669 *s = 0;
670
671 if (!XParseColor(MI_DISPLAY(mi), MI_COLORMAP(mi), f, &gp->fg))
672 {
673 (void) fprintf(stderr, "Glplanet: unparsable color: \"%s\"\n", f);
674 exit(1);
675 }
676 if (!XParseColor(MI_DISPLAY(mi), MI_COLORMAP(mi), b, &gp->bg))
677 {
678 (void) fprintf(stderr, "Glplanet: unparsable color: \"%s\"\n", f);
679 exit(1);
680 }
681
682 free(f);
683 free(b);
684 }
685
686
687 gp->window = MI_WINDOW(mi);
688 if ((gp->glx_context = init_GL(mi)) != NULL) {
689 reshape_glplanet(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
690 pinit(mi);
691 } else {
692 MI_CLEARWINDOW(mi);
693 }
694 }
695
696 ENTRYPOINT void
draw_glplanet(ModeInfo * mi)697 draw_glplanet(ModeInfo * mi)
698 {
699 planetstruct *gp = &planets[MI_SCREEN(mi)];
700 Display *display = MI_DISPLAY(mi);
701 Window window = MI_WINDOW(mi);
702
703 if (!gp->glx_context)
704 return;
705
706 MI_IS_DRAWN(mi) = True;
707
708 glDrawBuffer(GL_BACK);
709 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
710 #ifdef WIN32
711 wglMakeCurrent(hdc, gp->glx_context);
712 #else
713 glXMakeCurrent(display, window, *(gp->glx_context));
714 #endif
715
716 if (do_stars) {
717 /* protect our modelview matrix and attributes */
718 glPushMatrix();
719 glPushAttrib(GL_ALL_ATTRIB_BITS);
720 {
721 glColor3f(1,1,1);
722 /* draw the star field. */
723 glCallList(gp->starlist);
724
725 }
726 glPopMatrix();
727 glPopAttrib();
728 }
729
730 /* protect our modelview matrix and attributes */
731 glPushMatrix();
732 glPushAttrib(GL_ALL_ATTRIB_BITS);
733 {
734 /* this pair of rotations seem to be necessary to orient the earth correctly */
735 glRotatef(90,0,0,1);
736 glRotatef(90,0,1,0);
737
738 glTranslatef(gp->xpos, gp->ypos, gp->zpos);
739 glRotatef(gp->tx, 1, 0, 0);
740 glRotatef(gp->ty, 0, 1, 0);
741 glRotatef(gp->tz, 0, 0, 1);
742 /* draw the sphere */
743 draw_sphere_glp(mi);
744 }
745 glPopMatrix();
746 glPopAttrib();
747
748
749
750 if (MI_IS_FPS(mi)) do_fps (mi);
751 glFinish();
752 glXSwapBuffers(display, window);
753
754 rotate_and_move (mi);
755 }
756
757 ENTRYPOINT void
release_glplanet(ModeInfo * mi)758 release_glplanet(ModeInfo * mi)
759 {
760 if (planets != NULL) {
761 int screen;
762
763 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
764 planetstruct *gp = &planets[screen];
765
766 if (gp->glx_context) {
767 /* Display lists MUST be freed while their glXContext is current. */
768 #ifdef WIN32
769 wglMakeCurrent(hdc, gp->glx_context);
770 #else
771 glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
772 #endif
773
774 if (glIsList(gp->platelist))
775 glDeleteLists(gp->platelist, 1);
776 if (glIsList(gp->starlist))
777 glDeleteLists(gp->starlist, 1);
778 }
779 }
780 free(planets);
781 planets = (planetstruct *) NULL;
782 }
783 FreeAllGL(mi);
784 }
785
786 XSCREENSAVER_MODULE ("Glplanet", glplanet)
787
788 #endif /* MODE_glplanet */
789