2 static const char sccsid[] = "@(#)b_sphere.c 4.11 98/06/16 xlockmore";
6 * BUBBLE3D (C) 1998 Richard W.M. Jones.
7 * b_sphere.c: Create a list of vertices and triangles in a
8 * normalized sphere, which is then later used as the basic shape
9 * for all bubbles. This code is run once when the program starts
15 typedef glb_vertex vertex;
16 typedef glb_triangle triangle;
20 /* The list of vertices created. */
22 int nr_vertices, nr_vertices_allocated;
24 /* The list of triangles created. */
26 int nr_triangles, nr_triangles_allocated;
30 #define EPSILON GLB_VERTICES_EPSILON
32 /* Should be taken care of already... but just in case */
33 #if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
38 close_enough(const GLfloat * v1, const GLfloat * v2)
40 return fabs((double) (v1[0] - v2[0])) <= EPSILON &&
41 fabs((double) (v1[1] - v2[1])) <= EPSILON &&
42 fabs((double) (v1[2] - v2[2])) <= EPSILON;
45 #define INCR(n) ((n == 0) ? (n = 1) : (n *= 2))
46 #define INCR_ALLOCATION(a, n, t) (a = (t *) realloc (a, INCR (n) * sizeof (t)))
49 save_vertex(glb_data *d, const GLfloat * v)
53 /* Inefficient, but we only do this a few times. Check to see if there's
54 * an existing vertex which is `close enough' to this one.
56 for (i = 0; i < d->nr_vertices; ++i)
57 if (close_enough(v, d->vertices[i]))
60 if (d->nr_vertices_allocated <= d->nr_vertices) {
61 if (d->vertices == 0) {
62 d->vertices = (vertex *) malloc(INCR(d->nr_vertices_allocated) * sizeof (vertex));
64 INCR_ALLOCATION(d->vertices, d->nr_vertices_allocated, vertex);
67 d->vertices[d->nr_vertices][0] = v[0];
68 d->vertices[d->nr_vertices][1] = v[1];
69 d->vertices[d->nr_vertices][2] = v[2];
70 return d->nr_vertices++;
74 save_triangle(glb_data *d, GLuint v1, GLuint v2, GLuint v3)
76 if (d->nr_triangles_allocated <= d->nr_triangles) {
77 if (d->triangles == 0) {
78 d->triangles = (triangle *) malloc(INCR(d->nr_triangles_allocated) * sizeof (triangle));
80 INCR_ALLOCATION(d->triangles, d->nr_triangles_allocated, triangle);
83 d->triangles[d->nr_triangles][0] = v1;
84 d->triangles[d->nr_triangles][1] = v2;
85 d->triangles[d->nr_triangles][2] = v3;
86 return d->nr_triangles++;
90 normalize(GLfloat v[3])
92 GLfloat d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
99 v[0] = v[1] = v[2] = 0;
104 subdivide(glb_data *d,
105 const GLfloat * v1, GLuint vi1,
106 const GLfloat * v2, GLuint vi2,
107 const GLfloat * v3, GLuint vi3,
113 save_triangle(d, vi1, vi2, vi3);
115 GLuint vi12, vi23, vi31;
116 GLfloat v12[3], v23[3], v31[3];
118 for (i = 0; i < 3; ++i) {
119 v12[i] = v1[i] + v2[i];
120 v23[i] = v2[i] + v3[i];
121 v31[i] = v3[i] + v1[i];
124 vi12 = save_vertex(d, v12);
126 vi23 = save_vertex(d, v23);
128 vi31 = save_vertex(d, v31);
129 subdivide(d, v1, vi1, v12, vi12, v31, vi31, depth - 1);
130 subdivide(d, v2, vi2, v23, vi23, v12, vi12, depth - 1);
131 subdivide(d, v3, vi3, v31, vi31, v23, vi23, depth - 1);
132 subdivide(d, v12, vi12, v23, vi23, v31, vi31, depth - 1);
136 #define ICO_X 0.525731112119133606
137 #define ICO_Z 0.850650808352039932
139 static const GLfloat vdata[12][3] =
155 static const GLuint tindices[20][3] =
179 /* Public interface: Create the sphere. */
181 glb_sphere_init(void)
183 glb_data *d = (glb_data *) calloc (1, sizeof (*d));
186 for (i = 0; i < 20; ++i) {
187 subdivide(d, vdata[tindices[i][0]], save_vertex(d, vdata[tindices[i][0]]),
188 vdata[tindices[i][1]], save_vertex(d, vdata[tindices[i][1]]),
189 vdata[tindices[i][2]], save_vertex(d, vdata[tindices[i][2]]),
190 glb_config.subdivision_depth);
196 /* Return the vertices list. */
198 glb_sphere_get_vertices(glb_data *d, int *nr_vertices_ptr)
200 *nr_vertices_ptr = d->nr_vertices;
204 /* Return the triangles list. */
206 glb_sphere_get_triangles(glb_data *d, int *nr_triangles_ptr)
208 *nr_triangles_ptr = d->nr_triangles;
212 /* Free up memory. */
214 glb_sphere_end(glb_data *d)
216 (void) free((void *) d->vertices);
217 (void) free((void *) d->triangles);