http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[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 <math.h>
19 #include <stdlib.h>
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #ifdef HAVE_COCOA
26 # include <OpenGL/gl.h>
27 #else
28 # include <GL/gl.h>
29 #endif
30
31 #include "sphere.h"
32
33 typedef struct { GLfloat x, y, z; } XYZ;
34
35 void
36 unit_sphere (int stacks, int slices, int wire_p)
37 {
38   int i,j;
39   double theta1, theta2, theta3;
40   XYZ e, p;
41   XYZ la = { 0, 0, 0 }, lb = { 0, 0, 0 };
42   XYZ c = {0, 0, 0};  /* center */
43   double r = 1.0;     /* radius */
44   int stacks2 = stacks * 2;
45
46   if (r < 0)
47     r = -r;
48   if (slices < 0)
49     slices = -slices;
50
51   if (slices < 4 || stacks < 2 || r <= 0)
52     {
53       glBegin (GL_POINTS);
54       glVertex3f (c.x, c.y, c.z);
55       glEnd();
56       return;
57     }
58
59   glFrontFace(GL_CW);
60
61   for (j = 0; j < stacks; j++)
62     {
63       theta1 = j       * (M_PI+M_PI) / stacks2 - M_PI_2;
64       theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2;
65
66       glBegin (wire_p ? GL_LINE_LOOP : GL_TRIANGLE_STRIP);
67       for (i = 0; i <= slices; i++)
68         {
69           theta3 = i * (M_PI+M_PI) / slices;
70
71           if (wire_p && i != 0)
72             {
73               glVertex3f (lb.x, lb.y, lb.z);
74               glVertex3f (la.x, la.y, la.z);
75             }
76
77           e.x = cos (theta2) * cos(theta3);
78           e.y = sin (theta2);
79           e.z = cos (theta2) * sin(theta3);
80           p.x = c.x + r * e.x;
81           p.y = c.y + r * e.y;
82           p.z = c.z + r * e.z;
83
84           glNormal3f (e.x, e.y, e.z);
85           glTexCoord2f (i       / (double)slices,
86                         2*(j+1) / (double)stacks2);
87           glVertex3f (p.x, p.y, p.z);
88           if (wire_p) la = p;
89
90           e.x = cos(theta1) * cos(theta3);
91           e.y = sin(theta1);
92           e.z = cos(theta1) * sin(theta3);
93           p.x = c.x + r * e.x;
94           p.y = c.y + r * e.y;
95           p.z = c.z + r * e.z;
96
97           glNormal3f (e.x, e.y, e.z);
98           glTexCoord2f (i   / (double)slices,
99                         2*j / (double)stacks2);
100           glVertex3f (p.x, p.y, p.z);
101           if (wire_p) lb = p;
102         }
103       glEnd();
104     }
105 }