Ejemplo n.º 1
0
static void
push_gear (ModeInfo *mi)
{
  pinion_configuration *pp = &pps[MI_SCREEN(mi)];
  gear *g;
  gear *parent = (pp->ngears <= 0 ? 0 : pp->gears[pp->ngears-1]);

  Bool tried_coaxial_p = False;
  Bool coaxial_p = False;
  Bool last_ditch_coax_p = False;
  int loop_count = 0;

  pp->debug_size_failures = 0;
  pp->debug_position_failures = 0;

 AGAIN:
  loop_count++;
  if (loop_count > 100) abort();  /* we're doomed! */
  
  g = 0;

  /* If the gears are turning at LUDICROUS SPEED, unhook the train to
     reset things to a sane velocity.

     10,000 RPM at 30 FPS = 5.5 rotations per frame.
      1,000 RPM at 30 FPS = 0.5 rotations per frame.
        600 RPM at 30 FPS =  3 frames per rotation.
        200 RPM at 30 FPS =  9 frames per rotation.
        100 RPM at 30 FPS = 18 frames per rotation.
         50 RPM at 30 FPS = 36 frames per rotation.
         10 RPM at 30 FPS =  3 sec per rotation.
          1 RPM at 30 FPS = 30 sec per rotation.
         .5 RPM at 30 FPS =  1 min per rotation.
         .1 RPM at 30 FPS =  5 min per rotation.
   */
  if (parent && parent->rpm > max_rpm)
    {
      if (verbose_p)
        {
          char buf[100];
          rpm_string (parent->rpm, buf);
          fprintf (stderr, "%s: ludicrous speed!  %s\n\n", progname, buf);
        }
      parent = 0;
    }

  /* If the last N gears we've placed have all been motion-blurred, then
     it's a safe guess that we've wandered off into the woods and aren't
     coming back.  Bail on this train.
   */
  if (pp->current_blur_length >= 10)
    {
      if (verbose_p)
        fprintf (stderr, "%s: it's a blurpocalypse!\n\n", progname);
      parent = 0;
    }



  /* Sometimes, try to make a coaxial gear.
   */
  if (parent && !parent->coax_p && (random() % 40) == 0)
    {
      tried_coaxial_p = True;
      coaxial_p = True;
      g = place_new_gear (mi, parent, coaxial_p);
    }

  /* Try to make a regular gear.
   */
  if (!g)
    {
      coaxial_p = False;
      g = place_new_gear (mi, parent, coaxial_p);
    }

  /* If we couldn't make a regular gear, then try to make a coxial gear
     (unless we already tried that.)
   */
  if (!g && !tried_coaxial_p && parent && !parent->coax_p)
    {
      tried_coaxial_p = True;
      coaxial_p = True;
      g = place_new_gear (mi, parent, coaxial_p);
      if (g)
        last_ditch_coax_p = True;
    }

  /* If we couldn't do that either, then the train has hit a dead end:
     start a new train.
   */
  if (!g)
    {
      coaxial_p = False;
      if (verbose_p)
        fprintf (stderr, "%s: dead end!\n\n", progname);
      parent = 0;
      g = place_new_gear (mi, parent, coaxial_p);
    }

  if (! g)
    {
      /* Unable to make/place any gears at all!
         This can happen if we've backed ourself into a corner very near
         the top-right or bottom-right corner of the growth zone.
         It's time to add a gear, but there's no room to add one!
         In that case, let's just wipe all the gears that are in the
         growth zone and try again.
       */
      int i;

      if (verbose_p && debug_placement_p)
        fprintf (stderr,
                 "%s: placement: resetting growth zone!  "
                 "failed: %d size, %d pos\n",
                 progname,
                 pp->debug_size_failures, pp->debug_position_failures);
      for (i = pp->ngears-1; i >= 0; i--)
        {
          gear *g = pp->gears[i];
          if (g->x - g->r - g->tooth_h < pp->render_left)
            delete_gear (mi, g);
        }
      goto AGAIN;
    }

  if (g->coax_p)
    {
      if (g->x != parent->x) abort();
      if (g->y != parent->y) abort();
      if (g->z == parent->z) abort();
      if (g->r == parent->r) abort();
      if (g->th != parent->th) abort();
      if (g->ratio != parent->ratio) abort();
      if (g->rpm != parent->rpm) abort();
    }

  if (verbose_p)
    {
      fprintf (stderr, "%s: %5lu ", progname, g->id);

      fputc ((g->motion_blur_p ? '*' : ' '), stderr);
      fputc (((g->coax_p && last_ditch_coax_p) ? '2' :
              g->coax_p ? '1' : ' '),
             stderr);

      fprintf (stderr, " %2d%%",
               (int) (g->r * 2 * 100 / pp->vp_height));
      fprintf (stderr, "  %2d teeth", (int) g->nteeth);
      fprintf (stderr, " %3.0f rpm;", g->rpm);

      {
        char buf1[50], buf2[50], buf3[100];
        *buf1 = 0; *buf2 = 0; *buf3 = 0;
        if (pp->debug_size_failures)
          sprintf (buf1, "%3d sz", pp->debug_size_failures);
        if (pp->debug_position_failures)
          sprintf (buf2, "%2d pos", pp->debug_position_failures);
        if (*buf1 || *buf2)
          sprintf (buf3, " tries: %-7s%s", buf1, buf2);
        fprintf (stderr, "%-21s", buf3);
      }

      if (g->base_p) fprintf (stderr, " RESET %lu", pp->current_length);
      fprintf (stderr, "\n");
    }

  if (g->base_p)
    pp->current_length = 1;
  else
    pp->current_length++;

  if (g->motion_blur_p)
    pp->current_blur_length++;
  else
    pp->current_blur_length = 0;
}
Ejemplo n.º 2
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);
}