1 #if !defined( lint ) && !defined( SABER )
2 static const char sccsid[] = "@(#)b_draw.c 4.11 98/06/16 xlockmore";
7 * BUBBLE3D (C) 1998 Richard W.M. Jones.
8 * b_draw.c: This code creates new bubbles, manages them and controls
9 * them as they are drawn on the screen.
14 typedef struct draw_context {
15 /* The list of bubbles currently on the screen. */
19 /* When was the last time we created a new bubble? */
28 GLfloat mat_specular[] =
30 GLfloat mat_emission[] =
32 GLfloat mat_shininess[] =
36 GLfloat light_position[][4] =
41 GLfloat light_diffuse[][4] =
46 GLfloat light_specular[][4] =
52 /* Initialize the context. */
53 c = (struct draw_context *) malloc(sizeof (struct draw_context));
59 c->bubble_count = glb_config.create_bubbles_every;
61 /* Do some GL initialization. */
62 glClearColor(glb_config.bg_colour[0],
63 glb_config.bg_colour[1],
64 glb_config.bg_colour[2],
65 glb_config.bg_colour[3]);
67 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, glb_config.bubble_colour);
71 * E. Lassauge - 98/06/29
72 * Yeahh, cool ! Now that I know how to have random colors I
73 * patch this pretty beautiful mode too !!
75 GLfloat fred, fgreen, fblue;
78 fred = ((float) (NRAND(100)) / 100.0);
79 fgreen = ((float) (NRAND(100)) / 100.0);
80 /* I keep more blue */
81 fblue = ((float) (NRAND(50)) / 100.0) + 0.50;
86 /* For the moment don't play with ALPHA channel */
87 params[3] = glb_config.bubble_colour[3];
88 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, params);
91 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
92 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission);
93 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
96 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
99 glEnable(GL_LIGHTING);
106 glEnable(GL_DEPTH_TEST);
108 glEnable(GL_AUTO_NORMAL);
109 glEnable(GL_NORMALIZE);
112 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
114 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
115 glLightfv(GL_LIGHT0, GL_POSITION, light_position[0]);
116 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse[0]);
117 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular[0]);
118 glLightfv(GL_LIGHT1, GL_POSITION, light_position[1]);
119 glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse[1]);
120 glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular[1]);
121 glLightfv(GL_LIGHT2, GL_POSITION, light_position[2]);
122 glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse[2]);
123 glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular[2]);
129 delete_bubble(draw_context * c, int j)
133 glb_bubble_delete(c->bubble_list[j]);
135 for (i = j; i < c->nr_bubbles - 1; ++i)
136 c->bubble_list[i] = c->bubble_list[i + 1];
142 glb_draw_end(void *cc)
144 draw_context *c = (draw_context *) cc;
147 for (i = 0; i < c->nr_bubbles; ++i) {
151 (void) free((void *) c->bubble_list);
152 (void) free((void *) c);
156 create_new_bubbles(draw_context * c)
159 double r = glb_drand();
160 GLfloat size, speed, scale_incr, x, y, z;
162 void **old_bubble_list;
164 /* How many bubbles to make? */
165 if (r < glb_config.p_bubble_group[0])
167 else if (r < glb_config.p_bubble_group[1])
169 else if (r < glb_config.p_bubble_group[2])
174 /* Initial position of top-most bubble in group. */
175 x = glb_drand() * 4 - 2;
176 y = glb_config.screen_bottom;
177 z = glb_drand() * 2 - 2;
180 size = glb_config.min_size
181 + glb_drand() * (glb_config.max_size - glb_config.min_size);
184 speed = glb_config.min_speed
185 + glb_drand() * (glb_config.max_speed - glb_config.min_speed);
187 /* Work out the scaling increment. Bubbles should increase by scale_factor
188 * as they go from bottom to top of screen.
190 scale_incr = (size * glb_config.scale_factor - size)
191 / ((glb_config.screen_top - glb_config.screen_bottom) / speed);
193 /* Create the bubble(s). */
194 for (i = 0; i < n; ++i) {
195 if ((b[i] = glb_bubble_new(x, y, z, size, speed, scale_incr)) == 0) {
196 /* Out of memory - recover. */
199 glb_bubble_delete(b[i]);
202 /* Create the next bubble below the last bubble. */
206 /* Add the bubbles to the list. */
208 old_bubble_list = c->bubble_list;
209 if (c->bubble_list == 0) {
210 c->bubble_list = (void **) malloc(c->nr_bubbles * sizeof (void *));
212 c->bubble_list = (void **) realloc(c->bubble_list,
213 c->nr_bubbles * sizeof (void *));
216 if (c->bubble_list == 0) {
217 /* Out of memory - recover. */
218 for (i = 0; i < n; ++i)
219 glb_bubble_delete(b[i]);
220 c->bubble_list = old_bubble_list;
224 for (i = 0; i < n; ++i)
225 c->bubble_list[c->nr_bubbles - i - 1] = b[i];
231 glb_draw_step(void *cc)
233 draw_context *c = (draw_context *) cc;
236 /* Consider creating a new bubble or bubbles. */
237 if (c->nr_bubbles < glb_config.max_bubbles &&
238 c->bubble_count++ > glb_config.create_bubbles_every) {
239 if (create_new_bubbles(c))
242 /* Clear the display. */
243 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
245 /* XXX Draw the background here ... */
247 /* Draw all the bubbles on the display. */
248 for (i = 0; i < c->nr_bubbles; ++i) {
249 void *b = c->bubble_list[i];
254 /* Has the bubble reached the top of the screen? */
255 if (glb_bubble_get_y(b) >= glb_config.screen_top) {