X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fsphere.c;h=5aba74f0ddffbdf2c46dbe072f9ba2d84191d819;hp=d11eb9f10f79f9e83a8034793094ae89841a71c8;hb=cccbddbc4140cf9a06d7d95cc5c0ca36eb5d6e28;hpb=a94197e76a5dea5cb60542840809d6c20d0abbf3 diff --git a/hacks/glx/sphere.c b/hacks/glx/sphere.c index d11eb9f1..5aba74f0 100644 --- a/hacks/glx/sphere.c +++ b/hacks/glx/sphere.c @@ -1,4 +1,4 @@ -/* sphere, Copyright (c) 1998 David Konerding +/* sphere, Copyright (c) 2002 Paul Bourke * Utility function to create a unit sphere in GL. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -9,85 +9,88 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * 8-Oct-98: dek Released initial version of "glplanet" - * 21-Mar-01: jwz@jwz.org Broke sphere routine out into its own file. + * 8-Oct-98: dek Released initial version of "glplanet" + * 21-Mar-01: jwz@jwz.org Broke sphere routine out into its own file. + * 28-Feb-02: jwz@jwz.org New implementation from Paul Bourke: + * http://astronomy.swin.edu.au/~pbourke/opengl/sphere/ */ #include "config.h" #include #include #include -#include "tube.h" -/* Function for determining points on the surface of the sphere */ -static void -parametric_sphere (float theta, float rho, GLfloat *vector) -{ - vector[0] = -sin(theta) * sin(rho); - vector[1] = cos(theta) * sin(rho); - vector[2] = cos(rho); -} +typedef struct { GLfloat x, y, z; } XYZ; void unit_sphere (int stacks, int slices, Bool wire) { - int i, j; - float drho, dtheta; - float rho, theta; - GLfloat vector[3]; - GLfloat ds, dt, t, s; + int i,j; + double theta1, theta2, theta3; + XYZ e, p; + XYZ la, lb; + XYZ c = {0, 0, 0}; /* center */ + double r = 1.0; /* radius */ + int stacks2 = stacks * 2; - if (!wire) - glShadeModel(GL_SMOOTH); + if (r < 0) + r = -r; + if (slices < 0) + slices = -slices; + + if (slices < 4 || stacks < 2 || r <= 0) + { + glBegin (GL_POINTS); + glVertex3f (c.x, c.y, c.z); + glEnd(); + return; + } - /* Generate a sphere with quadrilaterals. - * Quad vertices are determined using a parametric sphere function. - * For fun, you could generate practically any parameteric surface and - * map an image onto it. - */ - drho = M_PI / stacks; - dtheta = 2.0 * M_PI / slices; - ds = 1.0 / slices; - dt = 1.0 / stacks; + glFrontFace(GL_CW); - glFrontFace(GL_CCW); - glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + for (j = 0; j < stacks; j++) + { + theta1 = j * (M_PI+M_PI) / stacks2 - M_PI_2; + theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2; - t = 0.0; - for (i=0; i < stacks; i++) { - rho = i * drho; - s = 0.0; - for (j=0; j < slices; j++) { - theta = j * dtheta; + glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_STRIP); + for (i = 0; i <= slices; i++) + { + theta3 = i * (M_PI+M_PI) / slices; - glTexCoord2f (s,t); - parametric_sphere (theta, rho, vector); - glNormal3fv (vector); - parametric_sphere (theta, rho, vector); - glVertex3f (vector[0], vector[1], vector[2]); + if (wire && i != 0) + { + glVertex3f (lb.x, lb.y, lb.z); + glVertex3f (la.x, la.y, la.z); + } - glTexCoord2f (s,t+dt); - parametric_sphere (theta, rho+drho, vector); - glNormal3fv (vector); - parametric_sphere (theta, rho+drho, vector); - glVertex3f (vector[0], vector[1], vector[2]); + 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; - glTexCoord2f (s+ds,t+dt); - parametric_sphere (theta + dtheta, rho+drho, vector); - glNormal3fv (vector); - parametric_sphere (theta + dtheta, rho+drho, vector); - glVertex3f (vector[0], vector[1], vector[2]); + glNormal3f (e.x, e.y, e.z); + glTexCoord2f (i / (double)slices, + 2*(j+1) / (double)stacks2); + glVertex3f (p.x, p.y, p.z); + if (wire) la = p; - glTexCoord2f (s+ds, t); - parametric_sphere (theta + dtheta, rho, vector); - glNormal3fv (vector); - parametric_sphere (theta + dtheta, rho, vector); - glVertex3f (vector[0], vector[1], vector[2]); + 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; - s = s + ds; + glNormal3f (e.x, e.y, e.z); + glTexCoord2f (i / (double)slices, + 2*j / (double)stacks2); + glVertex3f (p.x, p.y, p.z); + if (wire) lb = p; + } + glEnd(); } - t = t + dt; - } - glEnd(); }