1 #if !defined( lint ) && !defined( SABER )
2 static const char sccsid[] = "@(#)b_sphere.c 4.11 98/06/16 xlockmore";
7 * BUBBLE3D (C) 1998 Richard W.M. Jones.
8 * b_sphere.c: Create a list of vertices and triangles in a
9 * normalized sphere, which is then later used as the basic shape
10 * for all bubbles. This code is run once when the program starts
16 /* The list of vertices created. */
17 typedef glb_vertex vertex;
18 static vertex *vertices = 0;
19 static int nr_vertices = 0, nr_vertices_allocated = 0;
21 /* The list of triangles created. */
22 typedef glb_triangle triangle;
23 static triangle *triangles = 0;
24 static int nr_triangles = 0, nr_triangles_allocated = 0;
26 /* Have we initialized the lists yet? */
27 static int initialized = 0;
29 #define EPSILON GLB_VERTICES_EPSILON
31 /* Should be taken care of already... but just in case */
32 #if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
37 close_enough(GLfloat * v1, GLfloat * v2)
39 return fabs((double) (v1[0] - v2[0])) <= EPSILON &&
40 fabs((double) (v1[1] - v2[1])) <= EPSILON &&
41 fabs((double) (v1[2] - v2[2])) <= EPSILON;
44 #define INCR(n) ((n == 0) ? (n = 1) : (n *= 2))
45 #define INCR_ALLOCATION(a, n, t) (a = (t *) realloc (a, INCR (n) * sizeof (t)))
48 save_vertex(GLfloat * v)
52 /* Inefficient, but we only do this a few times. Check to see if there's
53 * an existing vertex which is `close enough' to this one.
55 for (i = 0; i < nr_vertices; ++i)
56 if (close_enough(v, vertices[i]))
59 if (nr_vertices_allocated <= nr_vertices) {
61 vertices = (vertex *) malloc(INCR(nr_vertices_allocated) * sizeof (vertex));
63 INCR_ALLOCATION(vertices, nr_vertices_allocated, vertex);
66 vertices[nr_vertices][0] = v[0];
67 vertices[nr_vertices][1] = v[1];
68 vertices[nr_vertices][2] = v[2];
73 save_triangle(GLuint v1, GLuint v2, GLuint v3)
75 if (nr_triangles_allocated <= nr_triangles) {
77 triangles = (triangle *) malloc(INCR(nr_triangles_allocated) * sizeof (triangle));
79 INCR_ALLOCATION(triangles, nr_triangles_allocated, triangle);
82 triangles[nr_triangles][0] = v1;
83 triangles[nr_triangles][1] = v2;
84 triangles[nr_triangles][2] = v3;
85 return nr_triangles++;
89 normalize(GLfloat v[3])
91 GLfloat d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
98 v[0] = v[1] = v[2] = 0;
103 subdivide(GLfloat * v1, GLuint vi1,
104 GLfloat * v2, GLuint vi2,
105 GLfloat * v3, GLuint vi3,
111 save_triangle(vi1, vi2, vi3);
113 GLuint vi12, vi23, vi31;
114 GLfloat v12[3], v23[3], v31[3];
116 for (i = 0; i < 3; ++i) {
117 v12[i] = v1[i] + v2[i];
118 v23[i] = v2[i] + v3[i];
119 v31[i] = v3[i] + v1[i];
122 vi12 = save_vertex(v12);
124 vi23 = save_vertex(v23);
126 vi31 = save_vertex(v31);
127 subdivide(v1, vi1, v12, vi12, v31, vi31, depth - 1);
128 subdivide(v2, vi2, v23, vi23, v12, vi12, depth - 1);
129 subdivide(v3, vi3, v31, vi31, v23, vi23, depth - 1);
130 subdivide(v12, vi12, v23, vi23, v31, vi31, depth - 1);
134 #define ICO_X 0.525731112119133606
135 #define ICO_Z 0.850650808352039932
137 static GLfloat vdata[12][3] =
153 static GLuint tindices[20][3] =
177 /* Public interface: Create the sphere. */
179 glb_sphere_init(void)
186 for (i = 0; i < 20; ++i) {
187 subdivide(vdata[tindices[i][0]], save_vertex(vdata[tindices[i][0]]),
188 vdata[tindices[i][1]], save_vertex(vdata[tindices[i][1]]),
189 vdata[tindices[i][2]], save_vertex(vdata[tindices[i][2]]),
190 glb_config.subdivision_depth);
196 /* Return the vertices list. */
198 glb_sphere_get_vertices(int *nr_vertices_ptr)
201 *nr_vertices_ptr = nr_vertices;
205 /* Return the triangles list. */
207 glb_sphere_get_triangles(int *nr_triangles_ptr)
210 *nr_triangles_ptr = nr_triangles;
214 /* Free up memory. */
221 (void) free((void *) vertices);
222 (void) free((void *) triangles);
225 nr_vertices = nr_vertices_allocated = 0;
228 nr_triangles = nr_triangles_allocated = 0;