1 /* sphere, Copyright (c) 2002 Paul Bourke <pbourke@swin.edu.au>,
2 * Copyright (c) 2010 Jamie Zawinski <jwz@jwz.org>
3 * Utility function to create a unit sphere in GL.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation. No representations are made about the suitability of this
10 * software for any purpose. It is provided "as is" without express or
13 * 8-Oct-98: dek Released initial version of "glplanet"
14 * 21-Mar-01: jwz@jwz.org Broke sphere routine out into its own file.
15 * 28-Feb-02: jwz@jwz.org New implementation from Paul Bourke:
16 * http://astronomy.swin.edu.au/~pbourke/opengl/sphere/
17 * 21-Aug-10 jwz@jwz.org Converted to use glDrawArrays, for OpenGL ES.
33 #endif /* HAVE_JWZGLES */
37 typedef struct { GLfloat x, y, z; } XYZ;
40 unit_sphere (int stacks, int slices, int wire_p)
44 double theta1, theta2, theta3;
46 XYZ la = { 0, -1, 0 }, lb = { 0, -1, 0 };
47 XYZ c = {0, 0, 0}; /* center */
48 double r = 1.0; /* radius */
49 int stacks2 = stacks * 2;
51 int mode = (wire_p ? GL_LINE_STRIP : GL_TRIANGLE_STRIP);
54 struct { XYZ p; XYZ n; GLfloat s, t; } *array;
61 arraysize = (stacks+1) * (slices+1) * (wire_p ? 4 : 2);
62 array = (void *) calloc (arraysize, sizeof(*array));
66 if (slices < 4 || stacks < 2 || r <= 0)
73 for (j = 0; j < stacks; j++)
75 theta1 = j * (M_PI+M_PI) / stacks2 - M_PI_2;
76 theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2;
78 for (i = slices; i >= 0; i--)
80 theta3 = i * (M_PI+M_PI) / slices;
84 array[out++].p = lb; /* vertex */
85 array[out++].p = la; /* vertex */
88 n.x = cos (theta2) * cos(theta3);
90 n.z = cos (theta2) * sin(theta3);
95 array[out].p = p; /* vertex */
96 array[out].n = n; /* normal */
97 array[out].s = i / (GLfloat) slices; /* texture */
98 array[out].t = 2*(j+1) / (GLfloat) stacks2;
103 n.x = cos(theta1) * cos(theta3);
105 n.z = cos(theta1) * sin(theta3);
110 array[out].p = p; /* vertex */
111 array[out].n = n; /* normal */
112 array[out].s = i / (GLfloat) slices; /* texture */
113 array[out].t = 2*j / (GLfloat) stacks2;
116 if (out >= arraysize) abort();
125 glEnableClientState (GL_VERTEX_ARRAY);
126 glEnableClientState (GL_NORMAL_ARRAY);
127 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
129 glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p);
130 glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n);
131 glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s);
133 glDrawArrays (mode, 0, out);