diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/b_sphere.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/glx/b_sphere.c')
-rw-r--r-- | hacks/glx/b_sphere.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/hacks/glx/b_sphere.c b/hacks/glx/b_sphere.c new file mode 100644 index 0000000..78be392 --- /dev/null +++ b/hacks/glx/b_sphere.c @@ -0,0 +1,219 @@ +#if 0 +static const char sccsid[] = "@(#)b_sphere.c 4.11 98/06/16 xlockmore"; +#endif + +/*- + * BUBBLE3D (C) 1998 Richard W.M. Jones. + * b_sphere.c: Create a list of vertices and triangles in a + * normalized sphere, which is then later used as the basic shape + * for all bubbles. This code is run once when the program starts + * up. + */ + +#include "bubble3d.h" + +typedef glb_vertex vertex; +typedef glb_triangle triangle; + +struct glb_data { + + /* The list of vertices created. */ + vertex *vertices; + int nr_vertices, nr_vertices_allocated; + + /* The list of triangles created. */ + triangle *triangles; + int nr_triangles, nr_triangles_allocated; +}; + + +#define EPSILON GLB_VERTICES_EPSILON + +/* Should be taken care of already... but just in case */ +#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus) +#undef inline +#define inline /* */ +#endif +static inline int +close_enough(const GLfloat * v1, const GLfloat * v2) +{ + return fabs((double) (v1[0] - v2[0])) <= EPSILON && + fabs((double) (v1[1] - v2[1])) <= EPSILON && + fabs((double) (v1[2] - v2[2])) <= EPSILON; +} + +#define INCR(n) ((n == 0) ? (n = 1) : (n *= 2)) +#define INCR_ALLOCATION(a, n, t) (a = (t *) realloc (a, INCR (n) * sizeof (t))) + +static inline GLuint +save_vertex(glb_data *d, const GLfloat * v) +{ + int i; + + /* Inefficient, but we only do this a few times. Check to see if there's + * an existing vertex which is `close enough' to this one. + */ + for (i = 0; i < d->nr_vertices; ++i) + if (close_enough(v, d->vertices[i])) + return i; + + if (d->nr_vertices_allocated <= d->nr_vertices) { + if (d->vertices == 0) { + d->vertices = (vertex *) malloc(INCR(d->nr_vertices_allocated) * sizeof (vertex)); + } else { + INCR_ALLOCATION(d->vertices, d->nr_vertices_allocated, vertex); + } + } + d->vertices[d->nr_vertices][0] = v[0]; + d->vertices[d->nr_vertices][1] = v[1]; + d->vertices[d->nr_vertices][2] = v[2]; + return d->nr_vertices++; +} + +static inline GLuint +save_triangle(glb_data *d, GLuint v1, GLuint v2, GLuint v3) +{ + if (d->nr_triangles_allocated <= d->nr_triangles) { + if (d->triangles == 0) { + d->triangles = (triangle *) malloc(INCR(d->nr_triangles_allocated) * sizeof (triangle)); + } else { + INCR_ALLOCATION(d->triangles, d->nr_triangles_allocated, triangle); + } + } + d->triangles[d->nr_triangles][0] = v1; + d->triangles[d->nr_triangles][1] = v2; + d->triangles[d->nr_triangles][2] = v3; + return d->nr_triangles++; +} + +static inline void +normalize(GLfloat v[3]) +{ + GLfloat d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] + v[2] * v[2])); + + if (d != 0) { + v[0] /= d; + v[1] /= d; + v[2] /= d; + } else { + v[0] = v[1] = v[2] = 0; + } +} + +static void +subdivide(glb_data *d, + const GLfloat * v1, GLuint vi1, + const GLfloat * v2, GLuint vi2, + const GLfloat * v3, GLuint vi3, + int depth) +{ + int i; + + if (depth == 0) { + save_triangle(d, vi1, vi2, vi3); + } else { + GLuint vi12, vi23, vi31; + GLfloat v12[3], v23[3], v31[3]; + + for (i = 0; i < 3; ++i) { + v12[i] = v1[i] + v2[i]; + v23[i] = v2[i] + v3[i]; + v31[i] = v3[i] + v1[i]; + } + normalize(v12); + vi12 = save_vertex(d, v12); + normalize(v23); + vi23 = save_vertex(d, v23); + normalize(v31); + vi31 = save_vertex(d, v31); + subdivide(d, v1, vi1, v12, vi12, v31, vi31, depth - 1); + subdivide(d, v2, vi2, v23, vi23, v12, vi12, depth - 1); + subdivide(d, v3, vi3, v31, vi31, v23, vi23, depth - 1); + subdivide(d, v12, vi12, v23, vi23, v31, vi31, depth - 1); + } +} + +#define ICO_X 0.525731112119133606 +#define ICO_Z 0.850650808352039932 + +static const GLfloat vdata[12][3] = +{ + {-ICO_X, 0, ICO_Z}, + {ICO_X, 0, ICO_Z}, + {-ICO_X, 0, -ICO_Z}, + {ICO_X, 0, -ICO_Z}, + {0, ICO_Z, ICO_X}, + {0, ICO_Z, -ICO_X}, + {0, -ICO_Z, ICO_X}, + {0, -ICO_Z, -ICO_X}, + {ICO_Z, ICO_X, 0}, + {-ICO_Z, ICO_X, 0}, + {ICO_Z, -ICO_X, 0}, + {-ICO_Z, -ICO_X, 0} +}; + +static const GLuint tindices[20][3] = +{ + {0, 4, 1}, + {0, 9, 4}, + {9, 5, 4}, + {4, 5, 8}, + {4, 8, 1}, + {8, 10, 1}, + {8, 3, 10}, + {5, 3, 8}, + {5, 2, 3}, + {2, 7, 3}, + {7, 10, 3}, + {7, 6, 10}, + {7, 11, 6}, + {11, 0, 6}, + {0, 1, 6}, + {6, 1, 10}, + {9, 0, 11}, + {9, 11, 2}, + {9, 2, 5}, + {7, 2, 11} +}; + +/* Public interface: Create the sphere. */ +glb_data * +glb_sphere_init(void) +{ + glb_data *d = (glb_data *) calloc (1, sizeof (*d)); + int i; + + for (i = 0; i < 20; ++i) { + subdivide(d, vdata[tindices[i][0]], save_vertex(d, vdata[tindices[i][0]]), + vdata[tindices[i][1]], save_vertex(d, vdata[tindices[i][1]]), + vdata[tindices[i][2]], save_vertex(d, vdata[tindices[i][2]]), + glb_config.subdivision_depth); + } + + return d; +} + +/* Return the vertices list. */ +glb_vertex * +glb_sphere_get_vertices(glb_data *d, int *nr_vertices_ptr) +{ + *nr_vertices_ptr = d->nr_vertices; + return d->vertices; +} + +/* Return the triangles list. */ +glb_triangle * +glb_sphere_get_triangles(glb_data *d, int *nr_triangles_ptr) +{ + *nr_triangles_ptr = d->nr_triangles; + return d->triangles; +} + +/* Free up memory. */ +void +glb_sphere_end(glb_data *d) +{ + (void) free((void *) d->vertices); + (void) free((void *) d->triangles); + free (d); +} |