diff options
| author | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
| commit | badef32037f52f79abc1f1440b786cd71afdf270 (patch) | |
| tree | 412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/glx/gears.c | |
| parent | Delete pre-6.00 files (diff) | |
| download | xscreensaver-master.tar.gz xscreensaver-master.tar.xz xscreensaver-master.zip | |
Diffstat (limited to 'hacks/glx/gears.c')
| -rw-r--r-- | hacks/glx/gears.c | 952 |
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 */ |
