ENTRYPOINT void init_gears (ModeInfo *mi) { gears_configuration *bp; int wire = MI_IS_WIREFRAME(mi); int i; if (!bps) { bps = (gears_configuration *) calloc (MI_NUM_SCREENS(mi), sizeof (gears_configuration)); if (!bps) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } } 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); } { 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 (); } if (!(random() % 8)) { planetary_gears (mi); } else { gear *g = 0; int total_gears = MI_COUNT (mi); int i; if (total_gears <= 0) total_gears = 3 + abs (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); }
/* Render one gear in the proper position, creating the gear's display list first if necessary. */ static void draw_gear (ModeInfo *mi, int which) { Bool wire_p = MI_IS_WIREFRAME(mi); pinion_configuration *pp = &pps[MI_SCREEN(mi)]; gear *g = pp->gears[which]; GLfloat th; Bool visible_p = (g->x + g->r + g->tooth_h >= pp->render_left && g->x - g->r - g->tooth_h <= pp->render_right); if (!visible_p && !debug_p) return; if (! g->dlist) { g->dlist = glGenLists (1); if (! g->dlist) { /* I don't know how many display lists a GL implementation is supposed to provide, but hopefully it's more than "a few hundred", or we'll be in trouble... */ check_gl_error ("glGenLists"); abort(); } glNewList (g->dlist, GL_COMPILE); g->polygons = draw_involute_gear (g, (wire_p && debug_p ? 2 : wire_p)); glEndList (); } glPushMatrix(); glTranslatef (g->x, g->y, g->z); if (g->motion_blur_p && !pp->button_down_p) { /* If we're in motion-blur mode, then draw the gear so that each frame rotates it by exactly one half tooth-width, so that it looks flickery around the edges. But, revert to the normal way when the mouse button is down lest the user see overlapping polygons. */ th = g->motion_blur_p * 180.0 / g->nteeth * (g->th > 0 ? 1 : -1); g->motion_blur_p++; } else th = g->th; glRotatef (th, 0, 0, 1); glPushName (g->id); if (! visible_p) mi->polygon_count += draw_involute_schematic (g, wire_p); else { glCallList (g->dlist); mi->polygon_count += g->polygons; } glPopName(); glPopMatrix(); }
ENTRYPOINT void init_mgears (ModeInfo *mi) { mgears_configuration *bp; int wire = MI_IS_WIREFRAME(mi); int i; if (!bps) { bps = (mgears_configuration *) calloc (MI_NUM_SCREENS(mi), sizeof (mgears_configuration)); if (!bps) { fprintf(stderr, "%s: out of memory\n", progname); exit(1); } } bp = &bps[MI_SCREEN(mi)]; bp->glx_context = init_GL(mi); reshape_mgears (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); } { double spin_speed = 0.5; double wander_speed = 0.01; double spin_accel = 2.0; 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, False /* don't randomize */ ); bp->trackball = gltrackball_init (); } { int total_gears = MI_COUNT(mi); double gears_per_turn; double gear_r, tw, th, thick, slope; int nubs, size; if (! (total_gears & 1)) total_gears++; /* must be odd or gears intersect */ /* Number of teeth must be odd if number of gears is odd, or teeth don't mesh when the loop closes. And since number of gears must be odd... */ if (! (teeth_arg & 1)) teeth_arg++; if (teeth_arg < 7) teeth_arg = 7; if (total_gears < 13) /* gear mesh angle is too steep with less */ total_gears = 13; thick = 0.2; nubs = (random() & 3) ? 0 : (random() % teeth_arg) / 2; slope = 0; /* Sloping gears are incompatible with "-roll" ... */ /* slope= -M_PI * 2 / total_gears; */ gears_per_turn = total_gears / 2.0; bp->ring_r = 3; gear_r = M_PI * bp->ring_r / gears_per_turn; tw = 0; th = gear_r * 2.5 / teeth_arg; /* If the gears are small, use a lower density mesh. */ size = (gear_r > 0.32 ? INVOLUTE_LARGE : gear_r > 0.13 ? INVOLUTE_MEDIUM : INVOLUTE_SMALL); /* If there are lots of teeth, use a lower density mesh. */ if (teeth_arg > 77) size = INVOLUTE_SMALL; if (teeth_arg > 45 && size == INVOLUTE_LARGE) size = INVOLUTE_MEDIUM; bp->ngears = total_gears; bp->gears = (mogear *) calloc (bp->ngears, sizeof(*bp->gears)); for (i = 0; i < bp->ngears; i++) { mogear *mg = &bp->gears[i]; gear *g = &mg->g; g->r = gear_r; g->size = size; g->nteeth = teeth_arg; g->tooth_w = tw; g->tooth_h = th; g->tooth_slope = slope; g->thickness = g->r * thick; g->thickness2 = g->thickness * 0.1; g->thickness3 = g->thickness; g->inner_r = g->r * 0.80; g->inner_r2 = g->r * 0.60; g->inner_r3 = g->r * 0.55; g->nubs = nubs; mg->pos_th = (M_PI * 2 / gears_per_turn) * i; mg->pos_thz = (M_PI / 2 / gears_per_turn) * i; g->th = ((i & 1) ? (M_PI * 2 / g->nteeth) : 0); /* Colorize */ g->color[0] = 0.7 + frand(0.3); g->color[1] = 0.7 + frand(0.3); g->color[2] = 0.7 + frand(0.3); 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]; /* Now render the gear into its display list. */ 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 (); } } }