Parametric Equation of a Sphere
and Texture Mapping
See also Creating spherical texture from 6 views Written by Paul Bourke
August 1996
One possible parameterisation of the sphere will be discussed along with the transformation required to texture map a sphere. An angle parameterisation of the sphere is
x = r sin(theta) cos(phi)
y = r sin(theta) sin(phi)
z = r cos(theta)
where r is the radius, theta the angle from the z axis (0 <= theta <= pi), and phi the angle from the x axis (0 <= phi <= 2pi). Textures are conventionally specified as rectangular images which are most easily parameterised by two cartesian type coordinates (u,v) say, where 0 <= u,v <= 1. The equation above for the sphere can be rewritten in terms of u and v as
x = r sin(v pi) cos(u 2 pi)
y = r sin(v pi) sin(u 2 pi)
z = r cos(v pi)
Solving for the u and v from the above gives
v = arccos(z/r) / pi
u = ( arccos(x/(r sin(v pi))) ) / (2 pi)
So, given a point (x,y,z) on the surface of the sphere the above gives the point (u,v) each component of which can be appropriately scaled to index into a texture image.
Note
A sphere cannot be "unwrapped" without distortion, for example, the length between points on the sphere will not equal the distance between points on the unwrapped plane.
When implementing this in code it is important to note that most implementations of arccos() returns value from 0 to pi and not 0 to 2 pi as the the formula above assumes. The second half cycle of the arccos function is obtained by noticing the sign of the y value. So the transformation written in C might be as follows
#define PI 3.141592654#define TWOPI 6.283185308void SphereMap(x,y,z,radius,u,v)double x,y,z,r,*u,*v;{ *v = acos(z/radius) / PI; if (y >= 0) *u = acos(x/(radius * sin(PI*(*v)))) / TWOPI; else *u = (PI + acos(x/(radius * sin(PI*(*v))))) / TWOPI;}There are still two special points, the exact north and south poles of the sphere, each of these two points needs to be "spread" out along the whole edge v=0 and v=1. In the formula above this is where sin(v pi) = 0.
OpenGL sphere with texture coordinates
Written by Paul Bourke
January 1999 A more efficient contribution by Federico Dosil: sphere.c
While straightforward many people seem to have trouble creating a sphere with texture coordinates. Here's the way I do it (written for clarity rather than efficiency).

Note
The whole line at the North pole and the South pole texture map onto a single point at the poles.
While this linear mapping of lines of latitude is fine for general textures, it may not be correct for particular image textures such as maps of the Earth. In those cases the latitude texture coordinates need to be matched to the latitude function used to make the image.

On many implementations triangle strips are muck efficient than quad strips. On the other hand triangle strips don't look so good in wireframe mode. Depending on personal taste the line glBegin(GL_QUAD_STRIP); can be replaced with glBegin(GL_TRIANGLE_STRIP);
/* Create a sphere centered at c, with radius r, and precision n Draw a point for zero radius spheres*/void CreateSphere(XYZ c,double r,int n){ int i,j; double theta1,theta2,theta3; XYZ e,p; if (r < 0) r = -r; if (n < 0) n = -n; if (n < 4 || r <= 0) { glBegin(GL_POINTS); glVertex3f(c.x,c.y,c.z); glEnd(); return; } for (j=0;j<n/2;j++) { theta1 = j * TWOPI / n - PID2; theta2 = (j + 1) * TWOPI / n - PID2; glBegin(GL_QUAD_STRIP); for (i=0;i<=n;i++) { theta3 = i * TWOPI / n; e.x = cos(theta2) * cos(theta3); e.y = sin(theta2); e.z = cos(theta2) * sin(theta3); p.x = c.x + r * e.x; p.y = c.y + r * e.y; p.z = c.z + r * e.z; glNormal3f(e.x,e.y,e.z); glTexCoord2f(i/(double)n,2*(j+1)/(double)n); glVertex3f(p.x,p.y,p.z); e.x = cos(theta1) * cos(theta3); e.y = sin(theta1); e.z = cos(theta1) * sin(theta3); p.x = c.x + r * e.x; p.y = c.y + r * e.y; p.z = c.z + r * e.z; glNormal3f(e.x,e.y,e.z); glTexCoord2f(i/(double)n,2*j/(double)n); glVertex3f(p.x,p.y,p.z); } glEnd(); }}It is a ssmall modification to enable one to create subsets of a sphere....3 dimensional wedges. As an example see the following code.
/* Create a sphere centered at c, with radius r, and precision n Draw a point for zero radius spheres Use CCW facet ordering "method" is 0 for quads, 1 for triangles (quads look nicer in wireframe mode) Partial spheres can be created using theta1->theta2, phi1->phi2 in radians 0 < theta < 2pi, -pi/2 < phi < pi/2*/void CreateSphere(XYZ c,double r,int n,int method, double theta1,double theta2,double phi1,double phi2){ int i,j; double t1,t2,t3; XYZ e,p; /* Handle special cases */ if (r < 0) r = -r; if (n < 0) n = -n; if (n < 4 || r <= 0) { glBegin(GL_POINTS); glVertex3f(c.x,c.y,c.z); glEnd(); return; } for (j=0;j<n/2;j++) { t1 = phi1 + j * (phi2 - phi1) / (n/2); t2 = phi1 + (j + 1) * (phi2 - phi1) / (n/2); if (method == 0) glBegin(GL_QUAD_STRIP); else glBegin(GL_TRIANGLE_STRIP); for (i=0;i<=n;i++) { t3 = theta1 + i * (theta2 - theta1) / n; e.x = cos(t1) * cos(t3); e.y = sin(t1); e.z = cos(t1) * sin(t3); p.x = c.x + r * e.x; p.y = c.y + r * e.y; p.z = c.z + r * e.z; glNormal3f(e.x,e.y,e.z); glTexCoord2f(i/(double)n,2*j/(double)n); glVertex3f(p.x,p.y,p.z); e.x = cos(t2) * cos(t3); e.y = sin(t2); e.z = cos(t2) * sin(t3); p.x = c.x + r * e.x; p.y = c.y + r * e.y; p.z = c.z + r * e.z; glNormal3f(e.x,e.y,e.z); glTexCoord2f(i/(double)n,2*(j+1)/(double)n); glVertex3f(p.x,p.y,p.z); } glEnd(); }}sphere.c