summaryrefslogtreecommitdiffstats
path: root/hacks/glx/b_draw.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/b_draw.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/glx/b_draw.c')
-rw-r--r--hacks/glx/b_draw.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/hacks/glx/b_draw.c b/hacks/glx/b_draw.c
new file mode 100644
index 0000000..977efbe
--- /dev/null
+++ b/hacks/glx/b_draw.c
@@ -0,0 +1,239 @@
+#if 0
+static const char sccsid[] = "@(#)b_draw.c 4.11 98/06/16 xlockmore";
+#endif
+
+/*-
+ * BUBBLE3D (C) 1998 Richard W.M. Jones.
+ * b_draw.c: This code creates new bubbles, manages them and controls
+ * them as they are drawn on the screen.
+ */
+
+#include "bubble3d.h"
+
+typedef struct draw_context {
+ /* The list of bubbles currently on the screen. */
+ void **bubble_list;
+ int nr_bubbles;
+
+ /* When was the last time we created a new bubble? */
+ int bubble_count;
+
+ glb_data *d;
+
+} draw_context;
+
+void *
+glb_draw_init(void)
+{
+ draw_context *c;
+
+ GLfloat mat_specular[] =
+ {1, 1, 1, 1};
+ GLfloat mat_emission[] =
+ {0, 0, 0, 1};
+ GLfloat mat_shininess[] =
+ {100};
+ GLfloat ambient[] =
+ {0.5, 0.5, 0.5, 1.0};
+ GLfloat light_position[][4] =
+ {
+ {0, -1, 0, 0},
+ {1, 1, 0, 0},
+ {-1, 0, 1, 0}};
+ GLfloat light_diffuse[][4] =
+ {
+ {1, 1, 1, 1},
+ {1, 1, 1, 1},
+ {1, 1, 1, 1}};
+ GLfloat light_specular[][4] =
+ {
+ {1, 1, 1, 1},
+ {1, 1, 1, 1},
+ {1, 1, 1, 1}};
+
+ /* Initialize the context. */
+ c = (struct draw_context *) malloc(sizeof (struct draw_context));
+
+ if (c == 0)
+ return 0;
+ c->bubble_list = 0;
+ c->nr_bubbles = 0;
+ c->bubble_count = glb_config.create_bubbles_every;
+
+ /* Do some GL initialization. */
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, glb_config.bubble_colour);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
+
+ if (glb_config.transparent_p)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_LIGHT2);
+
+ if (glb_config.transparent_p)
+ glEnable(GL_BLEND);
+ else
+ glEnable(GL_DEPTH_TEST);
+
+ glEnable(GL_AUTO_NORMAL);
+ glEnable(GL_NORMALIZE);
+
+ if (glb_config.transparent_p)
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position[0]);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse[0]);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular[0]);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position[1]);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse[1]);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular[1]);
+ glLightfv(GL_LIGHT2, GL_POSITION, light_position[2]);
+ glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse[2]);
+ glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular[2]);
+
+ c->d = glb_sphere_init();
+
+ return c;
+}
+
+static void
+delete_bubble(draw_context * c, int j)
+{
+ int i;
+
+ glb_bubble_delete(c->bubble_list[j]);
+
+ for (i = j; i < c->nr_bubbles - 1; ++i)
+ c->bubble_list[i] = c->bubble_list[i + 1];
+
+ c->nr_bubbles--;
+}
+
+void
+glb_draw_end(void *cc)
+{
+ draw_context *c = (draw_context *) cc;
+ int i;
+
+ for (i = 0; i < c->nr_bubbles; ++i) {
+ delete_bubble(c, i);
+ i--;
+ }
+
+ glb_sphere_end (c->d);
+
+ (void) free((void *) c->bubble_list);
+ (void) free((void *) c);
+}
+
+static int
+create_new_bubbles(draw_context * c)
+{
+ int n, i;
+ double r = glb_drand();
+ GLfloat size, speed, scale_incr, x, y, z;
+ void *b[4];
+ void **old_bubble_list;
+
+ /* How many bubbles to make? */
+ if (r < glb_config.p_bubble_group[0])
+ n = 1;
+ else if (r < glb_config.p_bubble_group[1])
+ n = 2;
+ else if (r < glb_config.p_bubble_group[2])
+ n = 3;
+ else
+ n = 4;
+
+ /* Initial position of top-most bubble in group. */
+ x = glb_drand() * 4 - 2;
+ y = glb_config.screen_bottom;
+ z = glb_drand() * 2 - 2;
+
+ /* What size? */
+ size = glb_config.min_size
+ + glb_drand() * (glb_config.max_size - glb_config.min_size);
+
+ /* What speed? */
+ speed = glb_config.min_speed
+ + glb_drand() * (glb_config.max_speed - glb_config.min_speed);
+
+ /* Work out the scaling increment. Bubbles should increase by scale_factor
+ * as they go from bottom to top of screen.
+ */
+ scale_incr = (size * glb_config.scale_factor - size)
+ / ((glb_config.screen_top - glb_config.screen_bottom) / speed);
+
+ /* Create the bubble(s). */
+ for (i = 0; i < n; ++i) {
+ if ((b[i] = glb_bubble_new(c->d, x, y, z, size, speed, scale_incr)) == 0) {
+ /* Out of memory - recover. */
+ i--;
+ while (i >= 0)
+ glb_bubble_delete(b[i]);
+ return 0;
+ }
+ /* Create the next bubble below the last bubble. */
+ y -= size * 3;
+ }
+
+ /* Add the bubbles to the list. */
+ c->nr_bubbles += n;
+ old_bubble_list = c->bubble_list;
+ if (c->bubble_list == 0) {
+ c->bubble_list = (void **) malloc(c->nr_bubbles * sizeof (void *));
+ } else {
+ c->bubble_list = (void **) realloc(c->bubble_list,
+ c->nr_bubbles * sizeof (void *));
+ }
+
+ if (c->bubble_list == 0) {
+ /* Out of memory - recover. */
+ for (i = 0; i < n; ++i)
+ glb_bubble_delete(b[i]);
+ c->bubble_list = old_bubble_list;
+ c->nr_bubbles -= n;
+ return 0;
+ }
+ for (i = 0; i < n; ++i)
+ c->bubble_list[c->nr_bubbles - i - 1] = b[i];
+
+ return 1;
+}
+
+void
+glb_draw_step(void *cc)
+{
+ draw_context *c = (draw_context *) cc;
+ int i;
+
+ /* Consider creating a new bubble or bubbles. */
+ if (c->nr_bubbles < glb_config.max_bubbles &&
+ c->bubble_count++ > glb_config.create_bubbles_every) {
+ if (create_new_bubbles(c))
+ c->bubble_count = 0;
+ }
+ /* Clear the display. */
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* XXX Draw the background here ... */
+
+ /* Draw all the bubbles on the display. */
+ for (i = 0; i < c->nr_bubbles; ++i) {
+ void *b = c->bubble_list[i];
+
+ glb_bubble_step(b);
+ glb_bubble_draw(c->d, b);
+
+ /* Has the bubble reached the top of the screen? */
+ if (glb_bubble_get_y(b) >= glb_config.screen_top) {
+ delete_bubble(c, i);
+ i--;
+ }
+ }
+}