X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fsphere.c;h=eb004b11814a14075f3603cf4fd07e38b3db52dc;hp=10e86d7698e1fd6b81229034067a9f5ae39deb73;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hpb=5f1f12f2a37da634000f96d18d59cc73a8814ef7 diff --git a/hacks/glx/sphere.c b/hacks/glx/sphere.c index 10e86d76..eb004b11 100644 --- a/hacks/glx/sphere.c +++ b/hacks/glx/sphere.c @@ -1,4 +1,5 @@ -/* sphere, Copyright (c) 2002, 2008 Paul Bourke +/* sphere, Copyright (c) 2002 Paul Bourke , + * Copyright (c) 2010 Jamie Zawinski * Utility function to create a unit sphere in GL. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -13,6 +14,7 @@ * 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/ + * 21-Aug-10 jwz@jwz.org Converted to use glDrawArrays, for OpenGL ES. */ #include @@ -38,71 +40,98 @@ unit_sphere (int stacks, int slices, int wire_p) int polys = 0; int i,j; double theta1, theta2, theta3; - XYZ e, p; + XYZ p, n; XYZ la = { 0, 0, 0 }, lb = { 0, 0, 0 }; XYZ c = {0, 0, 0}; /* center */ double r = 1.0; /* radius */ int stacks2 = stacks * 2; + int mode = (wire_p ? GL_LINE_LOOP : GL_TRIANGLE_STRIP); + + int arraysize, out; + struct { XYZ p; XYZ n; GLfloat s, t; } *array; + if (r < 0) r = -r; if (slices < 0) slices = -slices; + arraysize = (stacks+1) * (slices+1) * (wire_p ? 4 : 2); + array = (void *) calloc (arraysize, sizeof(*array)); + if (! array) abort(); + out = 0; + + if (slices < 4 || stacks < 2 || r <= 0) { - glBegin (GL_POINTS); - glVertex3f (c.x, c.y, c.z); - glEnd(); - return 1; + mode = GL_POINTS; + array[out++].p = c; + goto END; } - glFrontFace(GL_CW); - 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; - glBegin (wire_p ? GL_LINE_LOOP : GL_TRIANGLE_STRIP); - for (i = 0; i <= slices; i++) + for (i = slices; i >= 0; i--) { theta3 = i * (M_PI+M_PI) / slices; if (wire_p && i != 0) { - glVertex3f (lb.x, lb.y, lb.z); - glVertex3f (la.x, la.y, la.z); + array[out++].p = lb; /* vertex */ + array[out++].p = la; /* vertex */ } - 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)slices, - 2*(j+1) / (double)stacks2); - glVertex3f (p.x, p.y, p.z); + n.x = cos (theta2) * cos(theta3); + n.y = sin (theta2); + n.z = cos (theta2) * sin(theta3); + p.x = c.x + r * n.x; + p.y = c.y + r * n.y; + p.z = c.z + r * n.z; + + array[out].p = p; /* vertex */ + array[out].n = n; /* normal */ + array[out].s = i / (GLfloat) slices; /* texture */ + array[out].t = 2*(j+1) / (GLfloat) stacks2; + out++; + if (wire_p) la = p; - 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)slices, - 2*j / (double)stacks2); - glVertex3f (p.x, p.y, p.z); + n.x = cos(theta1) * cos(theta3); + n.y = sin(theta1); + n.z = cos(theta1) * sin(theta3); + p.x = c.x + r * n.x; + p.y = c.y + r * n.y; + p.z = c.z + r * n.z; + + array[out].p = p; /* vertex */ + array[out].n = n; /* normal */ + array[out].s = i / (GLfloat) slices; /* texture */ + array[out].t = 2*j / (GLfloat) stacks2; + out++; + + if (out >= arraysize) abort(); + if (wire_p) lb = p; polys++; } - glEnd(); } + + END: + + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_NORMAL_ARRAY); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); + + glVertexPointer (3, GL_FLOAT, sizeof(*array), &array[0].p); + glNormalPointer ( GL_FLOAT, sizeof(*array), &array[0].n); + glTexCoordPointer (2, GL_FLOAT, sizeof(*array), &array[0].s); + + glDrawArrays (mode, 0, out); + + free (array); + return polys; }