http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.02.tar.gz
[xscreensaver] / hacks / glx / sphere.c
1 /* sphere, Copyright (c) 2002 Paul Bourke <pbourke@swin.edu.au>
2  * Utility function to create a unit sphere in GL.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  *
12  *  8-Oct-98: dek          Released initial version of "glplanet"
13  * 21-Mar-01: jwz@jwz.org  Broke sphere routine out into its own file.
14  * 28-Feb-02: jwz@jwz.org  New implementation from Paul Bourke:
15  *                         http://astronomy.swin.edu.au/~pbourke/opengl/sphere/
16  */
17
18 #include "config.h"
19 #include <stdlib.h>
20 #include <math.h>
21 #include <GL/glx.h>
22
23
24 typedef struct { GLfloat x, y, z; } XYZ;
25
26 void
27 unit_sphere (int stacks, int slices, Bool wire)
28 {
29   int i,j;
30   double theta1, theta2, theta3;
31   XYZ e, p;
32   XYZ la, lb;
33   XYZ c = {0, 0, 0};  /* center */
34   double r = 1.0;     /* radius */
35   int stacks2 = stacks * 2;
36
37   if (r < 0)
38     r = -r;
39   if (slices < 0)
40     slices = -slices;
41
42   if (slices < 4 || stacks < 2 || r <= 0)
43     {
44       glBegin (GL_POINTS);
45       glVertex3f (c.x, c.y, c.z);
46       glEnd();
47       return;
48     }
49
50   glFrontFace(GL_CW);
51
52   for (j = 0; j < stacks; j++)
53     {
54       theta1 = j       * (M_PI+M_PI) / stacks2 - M_PI_2;
55       theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2;
56
57       glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_STRIP);
58       for (i = 0; i <= slices; i++)
59         {
60           theta3 = i * (M_PI+M_PI) / slices;
61
62           if (wire && i != 0)
63             {
64               glVertex3f (lb.x, lb.y, lb.z);
65               glVertex3f (la.x, la.y, la.z);
66             }
67
68           e.x = cos (theta2) * cos(theta3);
69           e.y = sin (theta2);
70           e.z = cos (theta2) * sin(theta3);
71           p.x = c.x + r * e.x;
72           p.y = c.y + r * e.y;
73           p.z = c.z + r * e.z;
74
75           glNormal3f (e.x, e.y, e.z);
76           glTexCoord2f (i       / (double)slices,
77                         2*(j+1) / (double)stacks2);
78           glVertex3f (p.x, p.y, p.z);
79           if (wire) la = p;
80
81           e.x = cos(theta1) * cos(theta3);
82           e.y = sin(theta1);
83           e.z = cos(theta1) * sin(theta3);
84           p.x = c.x + r * e.x;
85           p.y = c.y + r * e.y;
86           p.z = c.z + r * e.z;
87
88           glNormal3f (e.x, e.y, e.z);
89           glTexCoord2f (i   / (double)slices,
90                         2*j / (double)stacks2);
91           glVertex3f (p.x, p.y, p.z);
92           if (wire) lb = p;
93         }
94       glEnd();
95     }
96 }