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