summaryrefslogtreecommitdiffstats
path: root/hacks/glx/gears.c
diff options
context:
space:
mode:
authorSimon Rettberg2024-09-06 14:42:37 +0200
committerSimon Rettberg2024-09-06 14:42:37 +0200
commitbadef32037f52f79abc1f1440b786cd71afdf270 (patch)
tree412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/glx/gears.c
parentDelete pre-6.00 files (diff)
downloadxscreensaver-master.tar.gz
xscreensaver-master.tar.xz
xscreensaver-master.zip
Diffstat (limited to 'hacks/glx/gears.c')
-rw-r--r--hacks/glx/gears.c952
1 files changed, 0 insertions, 952 deletions
diff --git a/hacks/glx/gears.c b/hacks/glx/gears.c
deleted file mode 100644
index c8b2081..0000000
--- a/hacks/glx/gears.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/* gears, Copyright (c) 2007-2019 Jamie Zawinski <jwz@jwz.org>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. No representations are made about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * Originally written by Brian Paul in 1996 or earlier;
- * rewritten by jwz in Nov 2007.
- */
-
-#define DEFAULTS "*delay: 30000 \n" \
- "*count: 0 \n" \
- "*showFPS: False \n" \
- "*wireframe: False \n" \
- "*suppressRotationAnimation: True\n" \
-
-# define release_gears 0
-
-#include "xlockmore.h"
-#include "involute.h"
-#include "normals.h"
-#include "tube.h"
-#include "rotator.h"
-#include "gltrackball.h"
-#include <ctype.h>
-
-#ifdef USE_GL /* whole file */
-
-#undef BELLRAND
-#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
-
-#define DEF_SPIN "True"
-#define DEF_WANDER "True"
-#define DEF_SPEED "1.0"
-
-typedef struct {
- GLXContext *glx_context;
- rotator *rot;
- trackball_state *trackball;
- Bool button_down_p;
- Bool planetary_p;
-
- int ngears;
- gear **gears;
-
- GLuint armature_dlist;
- int armature_polygons;
-
- struct { GLfloat x1, y1, x2, y2; } bbox;
-
-} gears_configuration;
-
-static gears_configuration *bps = NULL;
-
-static Bool do_spin;
-static GLfloat speed;
-static Bool do_wander;
-
-static XrmOptionDescRec opts[] = {
- { "-spin", ".spin", XrmoptionNoArg, "True" },
- { "+spin", ".spin", XrmoptionNoArg, "False" },
- { "-speed", ".speed", XrmoptionSepArg, 0 },
- { "-wander", ".wander", XrmoptionNoArg, "True" },
- { "+wander", ".wander", XrmoptionNoArg, "False" },
-};
-
-static argtype vars[] = {
- {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool},
- {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
- {&speed, "speed", "Speed", DEF_SPEED, t_Float},
-};
-
-ENTRYPOINT ModeSpecOpt gears_opts = {countof(opts), opts, countof(vars), vars, NULL};
-
-
-/* Window management, etc
- */
-ENTRYPOINT void
-reshape_gears (ModeInfo *mi, int width, int height)
-{
- GLfloat h = (GLfloat) height / (GLfloat) width;
- int y = 0;
-
- if (width > height * 5) { /* tiny window: show middle */
- height = width * 9/16;
- y = -height/2;
- h = height / (GLfloat) width;
- }
-
- glViewport (0, y, (GLint) width, (GLint) height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective (30.0, 1/h, 1.0, 100.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt( 0.0, 0.0, 30.0,
- 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0);
-
- {
- GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi)
- ? (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi))
- : 1);
- glScalef (s, s, s);
- }
-
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-
-static void
-free_gear (gear *g)
-{
- if (g->dlist)
- glDeleteLists (g->dlist, 1);
- free (g);
-}
-
-
-/* Create and return a new gear sized for placement next to or on top of
- the given parent gear (if any.) Returns 0 if out of memory.
- [Mostly lifted from pinion.c]
- */
-static gear *
-new_gear (ModeInfo *mi, gear *parent)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
- gear *g = (gear *) calloc (1, sizeof (*g));
- static unsigned long id = 0; /* only used in debugging output */
-
- if (!g) return 0;
- g->id = ++id;
-
- /* Pick the size of the teeth.
- */
- if (parent) /* adjascent gears need matching teeth */
- {
- g->tooth_w = parent->tooth_w;
- g->tooth_h = parent->tooth_h;
- g->tooth_slope = -parent->tooth_slope;
- }
- else /* gears that begin trains get any size they want */
- {
- g->tooth_w = 0.007 * (1.0 + BELLRAND(4.0));
- g->tooth_h = 0.005 * (1.0 + BELLRAND(8.0));
-/*
- g->tooth_slope = ((random() % 8)
- ? 0
- : 0.5 + BELLRAND(1));
- */
- }
-
- /* Pick the number of teeth, and thus, the radius.
- */
- {
- double c;
-
- if (!parent || bp->ngears > 4)
- g->nteeth = 5 + BELLRAND (20);
- else
- g->nteeth = parent->nteeth * (0.5 + BELLRAND(2));
-
- c = g->nteeth * g->tooth_w * 2; /* circumference = teeth + gaps */
- g->r = c / (M_PI * 2); /* c = 2 pi r */
- }
-
- g->thickness = g->tooth_w + frand (g->r);
- g->thickness2 = g->thickness * 0.7;
- g->thickness3 = g->thickness;
-
- /* Colorize
- */
- g->color[0] = 0.5 + frand(0.5);
- g->color[1] = 0.5 + frand(0.5);
- g->color[2] = 0.5 + frand(0.5);
- g->color[3] = 1.0;
-
- g->color2[0] = g->color[0] * 0.85;
- g->color2[1] = g->color[1] * 0.85;
- g->color2[2] = g->color[2] * 0.85;
- g->color2[3] = g->color[3];
-
-
- /* Decide on shape of gear interior:
- - just a ring with teeth;
- - that, plus a thinner in-set "plate" in the middle;
- - that, plus a thin raised "lip" on the inner plate;
- - or, a wide lip (really, a thicker third inner plate.)
- */
- if ((random() % 10) == 0)
- {
- /* inner_r can go all the way in; there's no inset disc. */
- g->inner_r = (g->r * 0.1) + frand((g->r - g->tooth_h/2) * 0.8);
- g->inner_r2 = 0;
- g->inner_r3 = 0;
- }
- else
- {
- /* inner_r doesn't go in very far; inner_r2 is an inset disc. */
- g->inner_r = (g->r * 0.5) + frand((g->r - g->tooth_h) * 0.4);
- g->inner_r2 = (g->r * 0.1) + frand(g->inner_r * 0.5);
- g->inner_r3 = 0;
-
- if (g->inner_r2 > (g->r * 0.2))
- {
- int nn = (random() % 10);
- if (nn <= 2)
- g->inner_r3 = (g->r * 0.1) + frand(g->inner_r2 * 0.2);
- else if (nn <= 7 && g->inner_r2 >= 0.1)
- g->inner_r3 = g->inner_r2 - 0.01;
- }
- }
-
- /* If we have three discs, sometimes make the middle disc be spokes.
- */
- if (g->inner_r3 && ((random() % 5) == 0))
- {
- g->spokes = 2 + BELLRAND (5);
- g->spoke_thickness = 1 + frand(7.0);
- if (g->spokes == 2 && g->spoke_thickness < 2)
- g->spoke_thickness += 1;
- }
-
- /* Sometimes add little nubbly bits, if there is room.
- */
- if (g->nteeth > 5)
- {
- double size = 0;
- involute_biggest_ring (g, 0, &size, 0);
- if (size > g->r * 0.2 && (random() % 5) == 0)
- {
- g->nubs = 1 + (random() % 16);
- if (g->nubs > 8) g->nubs = 1;
- }
- }
-
- if (g->inner_r3 > g->inner_r2) abort();
- if (g->inner_r2 > g->inner_r) abort();
- if (g->inner_r > g->r) abort();
-
- /* Decide how complex the polygon model should be.
- */
- {
- double pix = g->tooth_h * MI_HEIGHT(mi); /* approx. tooth size in pixels */
- if (pix <= 2.5) g->size = INVOLUTE_SMALL;
- else if (pix <= 3.5) g->size = INVOLUTE_MEDIUM;
- else if (pix <= 25) g->size = INVOLUTE_LARGE;
- else g->size = INVOLUTE_HUGE;
- }
-
- g->base_p = !parent;
-
- return g;
-}
-
-
-/* Given a newly-created gear, place it next to its parent in the scene,
- with its teeth meshed and the proper velocity. Returns False if it
- didn't work. (Call this a bunch of times until either it works, or
- you decide it's probably not going to.)
- [Mostly lifted from pinion.c]
- */
-static Bool
-place_gear (ModeInfo *mi, gear *g, gear *parent)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
-
- /* Compute this gear's velocity.
- */
- if (! parent)
- {
- g->ratio = 0.8 + BELLRAND(0.4); /* 0.8-1.2 = 8-12rpm @ 60fps */
- g->th = 1; /* not 0 */
- }
- else
- {
- /* Gearing ratio is the ratio of the number of teeth to previous gear
- (which is also the ratio of the circumferences.)
- */
- g->ratio = (double) parent->nteeth / (double) g->nteeth;
-
- /* Set our initial rotation to match that of the previous gear,
- multiplied by the gearing ratio. (This is finessed later,
- once we know the exact position of the gear relative to its
- parent.)
- */
- g->th = -(parent->th * g->ratio);
-
- if (g->nteeth & 1) /* rotate 1/2 tooth-size if odd number of teeth */
- {
- double off = (180.0 / g->nteeth);
- if (g->th > 0)
- g->th += off;
- else
- g->th -= off;
- }
-
- /* ratios are cumulative for all gears in the train. */
- g->ratio *= parent->ratio;
- }
-
-
- if (parent) /* Place the gear next to the parent. */
- {
- double r_off = parent->r + g->r;
- int angle;
-
- angle = (random() % 360) - 180; /* -180 to +180 degrees */
-
- g->x = parent->x + (cos ((double) angle * (M_PI / 180)) * r_off);
- g->y = parent->y + (sin ((double) angle * (M_PI / 180)) * r_off);
- g->z = parent->z;
-
- /* avoid accidentally changing sign of "th" in the math below. */
- g->th += (g->th > 0 ? 360 : -360);
-
- /* Adjust the rotation of the gear so that its teeth line up with its
- parent, based on the position of the gear and the current rotation
- of the parent.
- */
- {
- double p_c = 2 * M_PI * parent->r; /* circumference of parent */
- double g_c = 2 * M_PI * g->r; /* circumference of g */
-
- double p_t = p_c * (angle/360.0); /* distance travelled along
- circumference of parent when
- moving "angle" degrees along
- parent. */
- double g_rat = p_t / g_c; /* if travelling that distance
- along circumference of g,
- ratio of g's circumference
- travelled. */
- double g_th = 360.0 * g_rat; /* that ratio in degrees */
-
- g->th += angle + g_th;
- }
- }
-
- /* If the position we picked for this gear causes it to overlap
- with any earlier gear in the train, give up.
- */
- {
- int i;
-
- for (i = bp->ngears-1; i >= 0; i--)
- {
- gear *og = bp->gears[i];
-
- if (og == g) continue;
- if (og == parent) continue;
- if (g->z != og->z) continue; /* Ignore unless on same layer */
-
- /* Collision detection without sqrt:
- d = sqrt(a^2 + b^2) d^2 = a^2 + b^2
- d < r1 + r2 d^2 < (r1 + r2)^2
- */
- if (((g->x - og->x) * (g->x - og->x) +
- (g->y - og->y) * (g->y - og->y)) <
- ((g->r + g->tooth_h + og->r + og->tooth_h) *
- (g->r + g->tooth_h + og->r + og->tooth_h)))
- return False;
- }
- }
-
- return True;
-}
-
-
-/* Make a new gear, place it next to its parent in the scene,
- with its teeth meshed and the proper velocity. Returns the gear;
- or 0 if it didn't work. (Call this a bunch of times until either
- it works, or you decide it's probably not going to.)
- [Mostly lifted from pinion.c]
- */
-static gear *
-place_new_gear (ModeInfo *mi, gear *parent)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
- int loop_count = 0;
- gear *g = 0;
-
- while (1)
- {
- loop_count++;
- if (loop_count >= 100)
- {
- if (g)
- free_gear (g);
- g = 0;
- break;
- }
-
- g = new_gear (mi, parent);
- if (!g) return 0; /* out of memory? */
-
- if (place_gear (mi, g, parent))
- break;
- }
-
- if (! g) return 0;
-
- /* We got a gear, and it is properly positioned.
- Insert it in the scene.
- */
- bp->gears[bp->ngears++] = g;
- return g;
-}
-
-
-static int
-arm (GLfloat length,
- GLfloat width1, GLfloat height1,
- GLfloat width2, GLfloat height2,
- Bool wire)
-{
- int polys = 0;
- glShadeModel(GL_FLAT);
-
-#if 0 /* don't need these - they're embedded in other objects */
- /* draw end 1 */
- glFrontFace(GL_CW);
- glNormal3f(-1, 0, 0);
- glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f(-length/2, -width1/2, -height1/2);
- glVertex3f(-length/2, width1/2, -height1/2);
- glVertex3f(-length/2, width1/2, height1/2);
- glVertex3f(-length/2, -width1/2, height1/2);
- polys++;
- glEnd();
-
- /* draw end 2 */
- glFrontFace(GL_CCW);
- glNormal3f(1, 0, 0);
- glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f(length/2, -width2/2, -height2/2);
- glVertex3f(length/2, width2/2, -height2/2);
- glVertex3f(length/2, width2/2, height2/2);
- glVertex3f(length/2, -width2/2, height2/2);
- polys++;
- glEnd();
-#endif
-
- /* draw top */
- glFrontFace(GL_CCW);
- glNormal3f(0, 0, -1);
- glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f(-length/2, -width1/2, -height1/2);
- glVertex3f(-length/2, width1/2, -height1/2);
- glVertex3f( length/2, width2/2, -height2/2);
- glVertex3f( length/2, -width2/2, -height2/2);
- polys++;
- glEnd();
-
- /* draw bottom */
- glFrontFace(GL_CW);
- glNormal3f(0, 0, 1);
- glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f(-length/2, -width1/2, height1/2);
- glVertex3f(-length/2, width1/2, height1/2);
- glVertex3f( length/2, width2/2, height2/2);
- glVertex3f( length/2, -width2/2, height2/2);
- polys++;
- glEnd();
-
- /* draw left */
- glFrontFace(GL_CW);
- glNormal3f(0, -1, 0);
- glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f(-length/2, -width1/2, -height1/2);
- glVertex3f(-length/2, -width1/2, height1/2);
- glVertex3f( length/2, -width2/2, height2/2);
- glVertex3f( length/2, -width2/2, -height2/2);
- polys++;
- glEnd();
-
- /* draw right */
- glFrontFace(GL_CCW);
- glNormal3f(0, 1, 0);
- glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
- glVertex3f(-length/2, width1/2, -height1/2);
- glVertex3f(-length/2, width1/2, height1/2);
- glVertex3f( length/2, width2/2, height2/2);
- glVertex3f( length/2, width2/2, -height2/2);
- polys++;
- glEnd();
-
- glFrontFace(GL_CCW);
-
- return polys;
-}
-
-
-static int
-ctube (GLfloat diameter, GLfloat width, Bool wire)
-{
- tube (0, 0, width/2,
- 0, 0, -width/2,
- diameter, 0,
- 32, True, True, wire);
- return 0; /* #### */
-}
-
-static void
-armature (ModeInfo *mi)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
-
- static const GLfloat spec[4] = {1.0, 1.0, 1.0, 1.0};
- GLfloat shiny = 128.0;
- GLfloat color[4];
-
- color[0] = 0.5 + frand(0.5);
- color[1] = 0.5 + frand(0.5);
- color[2] = 0.5 + frand(0.5);
- color[3] = 1.0;
-
- bp->armature_polygons = 0;
-
- bp->armature_dlist = glGenLists (1);
- if (! bp->armature_dlist)
- {
- check_gl_error ("glGenLists");
- abort();
- }
-
- glNewList (bp->armature_dlist, GL_COMPILE);
-
- glMaterialfv (GL_FRONT, GL_SPECULAR, spec);
- glMateriali (GL_FRONT, GL_SHININESS, shiny);
- glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
- glColor3f (color[0], color[1], color[2]);
-
- glPushMatrix();
-
- {
- GLfloat s = bp->gears[0]->r * 2.7;
- s = s/5.6;
- glScalef (s, s, s);
- }
-
- glTranslatef (0, 0, 1.4 + bp->gears[0]->thickness);
- glRotatef (30, 0, 0, 1);
-
- bp->armature_polygons += ctube (0.5, 10, wire); /* center axle */
-
- glPushMatrix();
- glTranslatef(0.0, 4.2, -1);
- bp->armature_polygons += ctube (0.5, 3, wire); /* axle 1 */
- glTranslatef(0, 0, 1.8);
- bp->armature_polygons += ctube (0.7, 0.7, wire);
- glPopMatrix();
-
- glPushMatrix();
- glRotatef(120, 0.0, 0.0, 1.0);
- glTranslatef(0.0, 4.2, -1);
- bp->armature_polygons += ctube (0.5, 3, wire); /* axle 2 */
- glTranslatef(0, 0, 1.8);
- bp->armature_polygons += ctube (0.7, 0.7, wire);
- glPopMatrix();
-
- glPushMatrix();
- glRotatef(240, 0.0, 0.0, 1.0);
- glTranslatef(0.0, 4.2, -1);
- bp->armature_polygons += ctube (0.5, 3, wire); /* axle 3 */
- glTranslatef(0, 0, 1.8);
- bp->armature_polygons += ctube (0.7, 0.7, wire);
- glPopMatrix();
-
- glTranslatef(0, 0, 1.5); /* center disk */
- bp->armature_polygons += ctube (1.5, 2, wire);
-
- glPushMatrix();
- glRotatef(270, 0, 0, 1);
- glRotatef(-10, 0, 1, 0);
- glTranslatef(-2.2, 0, 0);
- bp->armature_polygons += arm (4.0, 1.0, 0.5,
- 2.0, 1.0, wire); /* arm 1 */
- glPopMatrix();
-
- glPushMatrix();
- glRotatef(30, 0, 0, 1);
- glRotatef(-10, 0, 1, 0);
- glTranslatef(-2.2, 0, 0);
- bp->armature_polygons += arm (4.0, 1.0, 0.5,
- 2.0, 1.0, wire); /* arm 2 */
- glPopMatrix();
-
- glPushMatrix();
- glRotatef(150, 0, 0, 1);
- glRotatef(-10, 0, 1, 0);
- glTranslatef(-2.2, 0, 0);
- bp->armature_polygons += arm (4.0, 1.0, 0.5,
- 2.0, 1.0, wire); /* arm 3 */
- glPopMatrix();
-
- glPopMatrix();
-
- glEndList ();
-}
-
-
-static void
-planetary_gears (ModeInfo *mi)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
- gear *g0, *g1, *g2, *g3, *g4;
- GLfloat distance = 2.02;
-
- bp->planetary_p = True;
-
- g0 = new_gear (mi, 0);
- g1 = new_gear (mi, 0);
- g2 = new_gear (mi, 0);
- g3 = new_gear (mi, 0);
- g4 = new_gear (mi, 0);
-
- if (! place_gear (mi, g0, 0)) abort();
- if (! place_gear (mi, g1, 0)) abort();
- if (! place_gear (mi, g2, 0)) abort();
- if (! place_gear (mi, g3, 0)) abort();
- if (! place_gear (mi, g4, 0)) abort();
-
- g0->nteeth = 12 + (3 * (random() % 10)); /* must be multiple of 3 */
- g0->tooth_w = g0->r / g0->nteeth;
- g0->tooth_h = g0->tooth_w * 2.8;
-
-# define COPY(F) g4->F = g3->F = g2->F = g1->F = g0->F
- COPY(r);
- COPY(th);
- COPY(nteeth);
- COPY(tooth_w);
- COPY(tooth_h);
- COPY(tooth_slope);
- COPY(inner_r);
- COPY(inner_r2);
- COPY(inner_r3);
- COPY(thickness);
- COPY(thickness2);
- COPY(thickness3);
- COPY(ratio);
- COPY(size);
-# undef COPY
-
- g1->x = cos (M_PI * 2 / 3) * g1->r * distance;
- g1->y = sin (M_PI * 2 / 3) * g1->r * distance;
-
- g2->x = cos (M_PI * 4 / 3) * g2->r * distance;
- g2->y = sin (M_PI * 4 / 3) * g2->r * distance;
-
- g3->x = cos (M_PI * 6 / 3) * g3->r * distance;
- g3->y = sin (M_PI * 6 / 3) * g3->r * distance;
-
- g4->x = 0;
- g4->y = 0;
- g4->th = -g3->th;
-
- /* rotate central gear 1/2 tooth-size if odd number of teeth */
- if (g4->nteeth & 1)
- g4->th -= (180.0 / g4->nteeth);
-
- g0->inverted_p = True;
- g0->x = 0;
- g0->y = 0;
- g0->nteeth = g1->nteeth * 3;
- g0->r = g1->r * 3.05;
- g0->inner_r = g0->r * 0.8;
- g0->inner_r2 = 0;
- g0->inner_r3 = 0;
- g0->th = g1->th + (180 / g0->nteeth);
- g0->ratio = g1->ratio / 3;
-
- g0->tooth_slope = 0;
- g0->nubs = 3;
- g0->spokes = 0;
- g0->size = INVOLUTE_LARGE;
-
- bp->gears = (gear **) calloc (6, sizeof(*bp->gears));
- bp->ngears = 0;
-
- bp->gears[bp->ngears++] = g1;
- bp->gears[bp->ngears++] = g2;
- bp->gears[bp->ngears++] = g3;
- bp->gears[bp->ngears++] = g4;
- bp->gears[bp->ngears++] = g0;
-}
-
-
-
-
-ENTRYPOINT void
-init_gears (ModeInfo *mi)
-{
- gears_configuration *bp;
- int wire = MI_IS_WIREFRAME(mi);
- int i;
-
- MI_INIT (mi, bps);
-
- bp = &bps[MI_SCREEN(mi)];
-
- bp->glx_context = init_GL(mi);
-
- reshape_gears (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-
- if (!wire)
- {
- GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0};
- GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};
- GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
- GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0};
-
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
-
- glLightfv(GL_LIGHT0, GL_POSITION, pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
- glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
- }
-
- if (! bp->rot)
- {
- double spin_speed = 0.5;
- double wander_speed = 0.01;
- double spin_accel = 0.25;
-
- bp->rot = make_rotator (do_spin ? spin_speed : 0,
- do_spin ? spin_speed : 0,
- do_spin ? spin_speed : 0,
- spin_accel,
- do_wander ? wander_speed : 0,
- True
- );
- bp->trackball = gltrackball_init (True);
- }
-
- if (bp->gears)
- {
- for (i = 0; i < bp->ngears; i++)
- free_gear (bp->gears[i]);
- free (bp->gears);
- bp->gears = 0;
- bp->ngears = 0;
- }
-
- if (!(random() % 8))
- {
- planetary_gears (mi);
- }
- else
- {
- gear *g = 0;
- int total_gears = MI_COUNT (mi);
-
- bp->planetary_p = False;
-
- if (total_gears <= 0)
- total_gears = 3 + fabs (BELLRAND (8) - 4); /* 3 - 7, mostly 3. */
- bp->gears = (gear **) calloc (total_gears+2, sizeof(*bp->gears));
- bp->ngears = 0;
-
- for (i = 0; i < total_gears; i++)
- g = place_new_gear (mi, g);
- }
-
-
- /* Center gears in scene. */
- {
- GLfloat minx=99999, miny=99999, maxx=-99999, maxy=-99999;
- int i;
- for (i = 0; i < bp->ngears; i++)
- {
- gear *g = bp->gears[i];
- if (g->x - g->r < minx) minx = g->x - g->r;
- if (g->x + g->r > maxx) maxx = g->x + g->r;
- if (g->y - g->r < miny) miny = g->y - g->r;
- if (g->y + g->r > maxy) maxy = g->y + g->r;
- }
- bp->bbox.x1 = minx;
- bp->bbox.y1 = miny;
- bp->bbox.x2 = maxx;
- bp->bbox.y2 = maxy;
- }
-
- /* Now render each gear into its display list.
- */
- for (i = 0; i < bp->ngears; i++)
- {
- gear *g = bp->gears[i];
- g->dlist = glGenLists (1);
- if (! g->dlist)
- {
- check_gl_error ("glGenLists");
- abort();
- }
-
- glNewList (g->dlist, GL_COMPILE);
- g->polygons += draw_involute_gear (g, wire);
- glEndList ();
- }
- if (bp->planetary_p)
- armature (mi);
-}
-
-
-ENTRYPOINT void
-draw_gears (ModeInfo *mi)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
- Display *dpy = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
- int i;
-
- if (!bp->glx_context)
- return;
-
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
-
- glShadeModel(GL_SMOOTH);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_NORMALIZE);
- glEnable(GL_CULL_FACE);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix ();
-
- {
- double x, y, z;
- get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
- glTranslatef ((x - 0.5) * 4,
- (y - 0.5) * 4,
- (z - 0.5) * 7);
-
- gltrackball_rotate (bp->trackball);
-
- get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
-
- /* add a little rotation for -no-spin mode */
- x -= 0.14;
- y -= 0.06;
-
- glRotatef (x * 360, 1.0, 0.0, 0.0);
- glRotatef (y * 360, 0.0, 1.0, 0.0);
- glRotatef (z * 360, 0.0, 0.0, 1.0);
- }
-
- /* Center the scene's bounding box in the window,
- and scale it to fit.
- */
- {
- GLfloat w = bp->bbox.x2 - bp->bbox.x1;
- GLfloat h = bp->bbox.y2 - bp->bbox.y1;
- GLfloat s = 10.0 / (w > h ? w : h);
- glScalef (s, s, s);
- glTranslatef (-(bp->bbox.x1 + w/2),
- -(bp->bbox.y1 + h/2),
- 0);
- }
-
- mi->polygon_count = 0;
-
- for (i = 0; i < bp->ngears; i++)
- {
- gear *g = bp->gears[i];
-
- glPushMatrix();
-
- glTranslatef (g->x, g->y, g->z);
- glRotatef (g->th, 0, 0, 1);
-
- glCallList (g->dlist);
- mi->polygon_count += g->polygons;
-
- glPopMatrix ();
- }
-
- if (bp->planetary_p)
- {
- glCallList (bp->armature_dlist);
- mi->polygon_count += bp->armature_polygons;
- }
-
- glPopMatrix ();
-
- /* spin gears */
- if (!bp->button_down_p)
- for (i = 0; i < bp->ngears; i++)
- {
- gear *g = bp->gears[i];
- double off = g->ratio * 5 * speed;
- if (g->th > 0)
- g->th += off;
- else
- g->th -= off;
- }
-
- if (mi->fps_p) do_fps (mi);
- glFinish();
-
- glXSwapBuffers(dpy, window);
-}
-
-ENTRYPOINT Bool
-gears_handle_event (ModeInfo *mi, XEvent *event)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
-
- if (gltrackball_event_handler (event, bp->trackball,
- MI_WIDTH (mi), MI_HEIGHT (mi),
- &bp->button_down_p))
- return True;
- else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
- {
- init_gears (mi);
- return True;
- }
-
- return False;
-}
-
-
-ENTRYPOINT void
-free_gears (ModeInfo *mi)
-{
- gears_configuration *bp = &bps[MI_SCREEN(mi)];
- int i;
- if (!bp->glx_context) return;
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
- if (bp->rot) free_rotator (bp->rot);
- if (bp->trackball) gltrackball_free (bp->trackball);
- for (i = 0; i < bp->ngears; i++)
- if (bp->gears[i])
- free_gear (bp->gears[i]);
- if (glIsList(bp->armature_dlist))
- glDeleteLists (bp->armature_dlist, 1);
-
-}
-
-XSCREENSAVER_MODULE ("Gears", gears)
-
-#endif /* USE_GL */