예제 #1
0
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);
}
예제 #2
0
/* 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();
}
예제 #3
0
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 ();
      }
  }
}