1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* bubble3d.c - 3D bubbles */
5 static const char sccsid[] = "@(#)bubble3d.c 4.11 98/06/16 xlockmore";
9 * BUBBLE3D (C) 1998 Richard W.M. Jones.
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
25 * bubble.c: This code is responsible for creating and managing
26 * bubbles over their lifetime.
27 * The bubbles may be drawn inside out.
32 typedef struct bubble {
33 GLfloat *contributions; /* List of contributions from each
34 * nudge to each vertex. This list has
35 * length nr_vertices * nr_nudge_axes.
37 GLfloat x, y, z; /* (x,y,z) location of the bubble. */
38 GLfloat scale; /* Scaling factor applied to bubble. */
39 GLfloat y_incr, scale_incr; /* Change in y and scale each frame. */
40 GLfloat rotx, roty, rotz; /* Current rotation. */
41 GLfloat rotx_incr, roty_incr, rotz_incr; /* Amount by which we increase
44 GLfloat *nudge_angle; /* Current angle (radians) of each
45 * nudge. This list has length nr_nudge_axes.
47 GLfloat *nudge_angle_incr; /* Amount by which we increase each nudge
48 * angle in each frame.
53 /* Should be taken care of already... but just in case */
54 #if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
59 normalize(GLfloat v[3])
61 GLfloat d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] +
69 v[0] = v[1] = v[2] = 0;
74 dotprod(GLfloat * v1, GLfloat * v2)
76 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
80 max(GLfloat a, GLfloat b)
85 /* Create a new bubble. */
87 glb_bubble_new(glb_data *d, GLfloat x, GLfloat y, GLfloat z, GLfloat scale,
88 GLfloat y_incr, GLfloat scale_incr)
92 /* GLfloat axes [glb_config.nr_nudge_axes][3]; */
93 GLfloat axes[5][3]; /* HARD CODED for SunCC */
95 glb_vertex *vertices = glb_sphere_get_vertices(d, &nr_vertices);
97 bubble *b = (bubble *) malloc(sizeof *b);
102 if (glb_config.bubble_colour[0] == -1.0) {
103 b->color[0] = ((float) (NRAND(100)) / 100.0);
104 b->color[1] = ((float) (NRAND(100)) / 100.0);
105 b->color[2] = ((float) (NRAND(100)) / 100.0);
107 b->color[0] = glb_config.bubble_colour[0];
108 b->color[1] = glb_config.bubble_colour[1];
109 b->color[2] = glb_config.bubble_colour[2];
111 b->color[3] = glb_config.bubble_colour[3];
114 b->contributions = (GLfloat *) malloc(sizeof (GLfloat) * nr_vertices *
115 glb_config.nr_nudge_axes);
116 if (b->contributions == 0) {
117 (void) free((void *) b);
120 b->nudge_angle = (GLfloat *) malloc(sizeof (GLfloat) * glb_config.nr_nudge_axes);
121 if (b->nudge_angle == 0) {
122 (void) free((void *) b->contributions);
123 (void) free((void *) b);
126 b->nudge_angle_incr = (GLfloat *) malloc(sizeof (GLfloat) * glb_config.nr_nudge_axes);
127 if (b->nudge_angle_incr == 0) {
128 (void) free((void *) b->nudge_angle);
129 (void) free((void *) b->contributions);
130 (void) free((void *) b);
133 /* Initialize primitive elements. */
139 b->scale_incr = scale_incr;
140 b->rotx = b->roty = b->rotz = 0;
141 b->rotx_incr = glb_drand() * glb_config.rotation_factor * 2
142 - glb_config.rotation_factor;
143 b->roty_incr = glb_drand() * glb_config.rotation_factor * 2
144 - glb_config.rotation_factor;
145 b->rotz_incr = glb_drand() * glb_config.rotation_factor * 2
146 - glb_config.rotation_factor;
148 /* Initialize the nudge angle arrays. */
149 for (i = 0; i < glb_config.nr_nudge_axes; ++i) {
150 b->nudge_angle[i] = 0;
151 b->nudge_angle_incr[i] = glb_drand() * glb_config.nudge_angle_factor;
154 /* Choose some random nudge axes. */
155 for (i = 0; i < glb_config.nr_nudge_axes; ++i) {
156 axes[i][0] = glb_drand() * 2 - 1;
157 axes[i][1] = glb_drand() * 2 - 1;
158 axes[i][2] = glb_drand() * 2 - 1;
162 /* Calculate the contribution that each nudge axis has on each vertex. */
163 for (i = 0; i < nr_vertices; ++i)
164 for (j = 0; j < glb_config.nr_nudge_axes; ++j)
165 b->contributions[i * glb_config.nr_nudge_axes + j]
166 = max(0, dotprod(vertices[i], axes[j]));
171 /* Delete a bubble and free up all memory. */
173 glb_bubble_delete(void *bb)
175 bubble *b = (bubble *) bb;
178 if (b->nudge_angle_incr) {
179 (void) free((void *) b->nudge_angle_incr);
180 b->nudge_angle_incr = NULL;
182 if (b->nudge_angle) {
183 (void) free((void *) b->nudge_angle);
184 b->nudge_angle = NULL;
186 if (b->contributions) {
187 (void) free((void *) b->contributions);
188 b->contributions = NULL;
190 (void) free((void *) b);
195 /* Rotate and wobble a bubble by a single step. */
197 glb_bubble_step(void *bb)
200 bubble *b = (bubble *) bb;
202 /* Update the rotation. */
203 b->rotx += b->rotx_incr;
204 b->roty += b->roty_incr;
205 b->rotz += b->rotz_incr;
207 /* Update the nudge angles. */
208 for (i = 0; i < glb_config.nr_nudge_axes; ++i)
209 b->nudge_angle[i] += b->nudge_angle_incr[i];
211 /* Move it upwards & outwards. */
213 b->scale += b->scale_incr;
218 glb_bubble_draw(glb_data *d, void *bb)
221 bubble *b = (bubble *) bb;
223 glb_vertex *vertices = glb_sphere_get_vertices(d, &nr_vertices);
225 glb_triangle *triangles = glb_sphere_get_triangles(d, &nr_triangles);
226 glb_vertex *new_vertices;
228 new_vertices = (glb_vertex *) malloc(sizeof (glb_vertex) * nr_vertices);
229 /* Calculate the vertices of this bubble, factoring in each nudge axis. */
230 for (i = 0; i < nr_vertices; ++i) {
233 for (j = 0; j < glb_config.nr_nudge_axes; ++j)
234 s += ((GLfloat) cos((double) (b->nudge_angle[j])) *
235 glb_config.nudge_factor - glb_config.nudge_factor / 2) *
236 b->contributions[i * glb_config.nr_nudge_axes + j];
238 new_vertices[i][0] = vertices[i][0] * (s + 1);
239 new_vertices[i][1] = vertices[i][1] * (s + 1);
240 new_vertices[i][2] = vertices[i][2] * (s + 1);
245 /* Apply translation, rotation and scalings. */
246 glTranslatef(b->x, b->y, b->z);
248 glRotatef(b->rotx, 1, 0, 0);
249 glRotatef(b->roty, 0, 1, 0);
250 glRotatef(b->rotz, 0, 0, 1);
252 glScalef(b->scale, b->scale, b->scale);
254 /* Draw the bubble. */
255 glBegin(GL_TRIANGLES);
257 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, b->color);
259 for (i = 0; i < nr_triangles; ++i) {
260 glNormal3fv(new_vertices[triangles[i][0]]);
261 glVertex3fv(new_vertices[triangles[i][0]]);
262 glNormal3fv(new_vertices[triangles[i][1]]);
263 glVertex3fv(new_vertices[triangles[i][1]]);
264 glNormal3fv(new_vertices[triangles[i][2]]);
265 glVertex3fv(new_vertices[triangles[i][2]]);
269 (void) free((void *) new_vertices);
270 glb_config.polygon_count += nr_triangles;
273 /* Return y value. */
275 glb_bubble_get_y(void *bb)
277 bubble *b = (bubble *) bb;