home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / bomb.tar.gz / bomb.tar / bomb / rotor.c < prev    next >
C/C++ Source or Header  |  1998-01-08  |  11KB  |  482 lines

  1. /*
  2.     bomb - automatic interactive visual stimulation
  3.     Copyright (C) 1994  Scott Draves <spot@cs.cmu.edu>
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include "defs.h"
  21. #include "bomb.h"
  22. #include "libifs.h"
  23. #include "sound.h"
  24.  
  25. // double cc[NXFORMS][3][2];
  26.  
  27. ifs_control_point cc_direction;
  28.  
  29. #define nsamples 1000
  30. #define nbatches 10
  31. #define bufsize (nsamples/nbatches)
  32. ifs_point p_buf[bufsize];
  33.  
  34.  
  35. /*
  36.  * a rotor is the sum of spinners (n=~3).  each spinner's speed&radius
  37.  * wanders piecewise linear over a range, uniform dist.  originally from
  38.  * Tom Lawrence (tcl@cs.brown.edu: 'flight' simulator, now at SGI), put
  39.  * into xlock (by Steve Zellers, zellers@sun.com), maintained there by
  40.  * Patrick J. Naughton.  
  41.  */
  42.  
  43. #define MAX_SPINNERS 10
  44.  
  45. typedef struct {
  46.    int radius_steps, speed_steps;
  47.    double radius, dradius;
  48.    double speed, dspeed;
  49. } spinner;
  50.  
  51. double spinner_time = 0.0;
  52. int nspinners;
  53. spinner spinners[MAX_SPINNERS];
  54.  
  55.  
  56. int nspin2;
  57. spinner spin2[MAX_SPINNERS];
  58.  
  59.  
  60. void init_spinner(int *nspin, spinner *spin)
  61. {
  62.    int i;
  63.    int n = (R%2) ? 3 : ((R%3)?2:4);
  64.    if (n > MAX_SPINNERS)
  65.       n = MAX_SPINNERS;
  66.    *nspin = n;
  67. #define KRS 30000
  68.    for (i = 0; i < n; i++) {
  69.       spin[i].radius_steps = KRS;
  70.       spin[i].speed_steps = KRS;
  71.       spin[i].radius = (R%100-25)/50.0;
  72.       spin[i].speed  = 0.1 + (R%100)/20.0;
  73.       spin[i].dradius = (R%100-50)/(50.0*KRS);
  74.       spin[i].dspeed  = (R%100-50)/(20.0*KRS);
  75.    }
  76. }
  77.  
  78. void init_rotate()
  79. {
  80.    init_spinner(&nspinners, spinners);
  81.    init_spinner(&nspin2, spin2);
  82. }
  83.  
  84.  
  85. int nice_ratio0(double r) {
  86.     int k = 0.1;
  87.     if (0.1 > abs(r - floor(r))) return 1;
  88.     if (0.05 > abs(2*r - floor(2*r))) return 1;
  89.     if (0.033 > abs(3*r - floor(3*r))) return 1;
  90.     if (0.025 > abs(4*r - floor(4*r))) return 1;
  91.     return 0;
  92. }
  93.  
  94. int nice_ratio(double r) {
  95.     return nice_ratio0(r) || nice_ratio0(1.0/r);
  96. }
  97.  
  98. void rotate(int *nspin, spinner *spin, double *xy)
  99. {
  100.    double x, y;
  101.    int i;
  102.    int n = *nspin;
  103.     int found_good_ratio = 0;
  104.     int search_steps = 0;
  105. #define SI spin[i]
  106.  
  107.    while (search_steps++ < 50 && !found_good_ratio) {
  108.      for (i = 0; i < n; i++) {
  109.         SI.radius += SI.dradius;
  110.         SI.speed += SI.dspeed;
  111.          if (!nice_ratio(SI.speed / spin[0].speed)) {
  112.             spinner_time += 0.04;
  113.             break;
  114.         }
  115.      }
  116.      found_good_ratio = (i == n);
  117.    }
  118.  
  119.  
  120.    x = y = 0.0;
  121.    for (i = 0; i < n; i++) {
  122.       x += SI.radius * cos(SI.speed * spinner_time);
  123.       y += SI.radius * sin(SI.speed * spinner_time);
  124.       if (0 == SI.radius_steps--) {
  125.      double goal = (R%100)/100.0+(R%100)/100.0;
  126.      SI.radius_steps = KRS;
  127.      SI.dradius = (goal - SI.radius) / KRS;
  128.       }
  129.       if (0 == SI.speed_steps--) {
  130.      double goal = 0.1 + (R%100)/20.0;
  131.      SI.speed_steps = KRS;
  132.      SI.dspeed = (goal - SI.speed) / KRS;
  133.       }
  134.    }
  135.    x = x / n;
  136.    y = y / n;
  137.  
  138.    xy[0] = x;
  139.    xy[1] = y;
  140. }
  141.  
  142.  
  143. int rotate_int(int *nspin, spinner *spin, int *ixy)
  144. {
  145.    double xy[2];
  146.    rotate(nspin, spin, xy);
  147.    ixy[0] = (xy[0]+1) * (XSIZE/2);
  148.    ixy[1] = (xy[1]+1) * (YSIZE/2);
  149. }
  150.  
  151.  
  152.  
  153.  
  154. /* flame support code */
  155.  
  156. void normalize_liss_coefs()
  157. {
  158.    int i, j, k;
  159.    double r;
  160.    for (i = 0; i < NXFORMS; i++) {
  161.       r = 1e-6;
  162.       for (j = 0; j < 3; j++)
  163.      for (k = 0; k < 2; k++) {
  164.        double t;
  165.         t = cc_direction.xform[j].c[k][i];
  166.         r += t * t;
  167.      }
  168.       r = 0.015 / sqrt(r);
  169.       for (j = 0; j < 3; j++)
  170.      for (k = 0; k < 2; k++)
  171.         cc_direction.xform[j].c[k][i] *= r;
  172.    }
  173. }
  174. void pick_liss_coefs()
  175. {
  176.    int i, j, k;
  177.    double r;
  178.    for (i = 0; i < NXFORMS; i++) {
  179.       r = 1e-6;
  180.       for (j = 0; j < 3; j++)
  181.      for (k = 0; k < 2; k++) {
  182.        double t;
  183.         cc_direction.xform[j].c[k][i] = random_uniform11();
  184.      }
  185.    }
  186.    normalize_liss_coefs();
  187. }
  188.  
  189. int nflames;
  190. ifs_control_point flames[MAXFLAMES];
  191.  
  192. void init_rotor()
  193. {
  194.    char sbuffer[4000];
  195.    char *ss = sbuffer;
  196.    int c, i, n = 0;
  197.    FILE *f;
  198.  
  199.    if (getenv("quick"))
  200.       goto quick;
  201.  
  202.    sprintf(sbuffer, "%sflame-data", DATA_DIR);
  203.    f = fopen(sbuffer, "r");
  204.  
  205.    if (NULL == f)
  206.       goto fail;
  207.    while (1) {
  208.       i = 0;
  209.       ss = sbuffer;
  210.       do {
  211.      c = fgetc(f);
  212.      if (EOF == c)
  213.         goto done_reading;
  214.      sbuffer[i++] = c;
  215.       } while (';' != c);
  216.       parse_control_point(&ss, flames + n);
  217.       n++;
  218.       if (n == MAXFLAMES)
  219.      goto done_reading;
  220.    }
  221.  done_reading:
  222.    nflames = n;
  223.    if (n > 0)
  224.       return;
  225.  fail:
  226.    fprintf(stderr, "flame-data not read\n");
  227.  quick:
  228.    random_control_point(flames);
  229. }
  230.  
  231.  
  232. rotcp(rule_t *p, double by)
  233. {
  234.    double s, t;
  235.    int i;
  236.    for (i = 0; i < NXFORMS; i++) {
  237.       double r[2][2];
  238.       double T[2][2];
  239.       double U[2][2];
  240.       double dtheta = by * 8.0 * M_PI / (1000.0 * nbatches);
  241.  
  242.       r[1][1] = r[0][0] = cos(dtheta);
  243.       r[0][1] = sin(dtheta);
  244.       r[1][0] = -r[0][1];
  245.       T[0][0] = p->flame_cp.xform[i].c[0][0];
  246.       T[1][0] = p->flame_cp.xform[i].c[1][0];
  247.       T[0][1] = p->flame_cp.xform[i].c[0][1];
  248.       T[1][1] = p->flame_cp.xform[i].c[1][1];
  249.       mult_matrix(r, T, U);
  250.       p->flame_cp.xform[i].c[0][0] = U[0][0];
  251.       p->flame_cp.xform[i].c[1][0] = U[1][0];
  252.       p->flame_cp.xform[i].c[0][1] = U[0][1];
  253.       p->flame_cp.xform[i].c[1][1] = U[1][1];
  254.    }
  255. }
  256.  
  257. rot_point(rule_t *p, double by)
  258. {
  259.    int i;
  260.    for (i = 0; i < NXFORMS; i++) {
  261.       double s[2];
  262.       double r[2][2];
  263.       double dtheta = by * 8.0 * M_PI / (1000.0 * nbatches);
  264.       r[1][1] = r[0][0] = cos(dtheta);
  265.       r[0][1] = sin(dtheta);
  266.       r[1][0] = -r[0][1];
  267.       s[0] = p->flame_cp.xform[i].c[2][0];
  268.       s[1] = p->flame_cp.xform[i].c[2][1];
  269.       
  270.      
  271.       p->flame_cp.xform[i].c[2][0] =
  272.      s[0] * r[0][0] + s[1] * r[0][1];
  273.       p->flame_cp.xform[i].c[2][1] =
  274.      s[0] * r[1][0] + s[1] * r[1][1];
  275.    }
  276. }
  277.  
  278. int gong = 0;
  279.  
  280. void step_rule_rotorug(int frame, rule_t *p, image8_t *fb)
  281. {
  282.    int x,y,bx,by,i;
  283.    board_t *sboard, *dboard;
  284.    u_char *lp;
  285.    int drift_type = iclamp(p->drift, 9);
  286.    int bsize = p->bsize/15;
  287. #ifndef wbomb
  288.    if (bsize < 1) bsize = 1;
  289.    else
  290. #endif
  291.    if (bsize > 8) bsize /= 2;
  292.    if (bsize > 8) bsize /= 2;
  293.  
  294.    if (sound_present && p->speed_beat_size) {
  295.      bsize = (p->drift_speed - 12) / 2;
  296.      if (bsize < 0) bsize = 0;
  297.      bsize = 1+sqrt(bsize);
  298.    }
  299.  
  300.    sboard = &board[dbuf];
  301.    dboard = &board[1-dbuf];
  302.    dbuf = 1-dbuf;
  303.  
  304.    if (2 == drift_type) {
  305.      if (gong > 0)
  306.        gong--;
  307.      for (i = 0; i < NXFORMS; i++) {
  308.        double r;
  309.        r = (p->flame_cp.xform[i].c[0][0] *
  310.         p->flame_cp.xform[i].c[1][1]) -
  311.      (p->flame_cp.xform[i].c[0][1] *
  312.       p->flame_cp.xform[i].c[1][0]);
  313.        if (r > 3 || r < -3)
  314.      gong += 10;
  315.        if (0)
  316.      printf("%.3g(%.3g) ", r, p->flame_cp.xform[i].density);
  317.      }
  318.      if (0 /* gong > 800 */) {
  319.        gong = 0;
  320.        random_control_point(&rule.flame_cp);
  321.        pick_liss_coefs();
  322.      }
  323.      if (0) printf("%d\n", gong);
  324.    }
  325.  
  326.  
  327.    for(y=1;y<=YSIZE;y++) {
  328.       lp = fb->p + (fb->stride * (y - 1));
  329.       for(x=1;x<=XSIZE;x++) {
  330.      int t;
  331.      t = ((((*sboard)[x  ][y-1]) +
  332.            ((*sboard)[x-1][y  ]<<1) +
  333.            ((*sboard)[x  ][y  ]<<1) +
  334.            ((*sboard)[x+1][y  ]<<1) +
  335.            ((*sboard)[x  ][y+1])
  336.            + p->speed) >> 3);
  337.      if (t<0) t = 0;
  338.      t &= p->mask;
  339.      (*dboard)[x][y]= t;
  340.     // if (p->remap)
  341.         t = remap[t];
  342.      *(lp++)=t;
  343.       }
  344.    }
  345.    if (1 >= drift_type) {
  346.       for (i = 0; i < 200; i++)  {
  347.      int xy[2];
  348.      spinner_time += 0.04;
  349.      rotate_int(&nspinners, spinners, xy);
  350.      x = xy[0];
  351.      switch (drift_type) {
  352.       case 0:
  353.         /* circular (original) */
  354.         y = xy[1];
  355.         break;
  356. #if 0
  357.       case 1:
  358.         /* rectangular */
  359.         rotate_int(&nspin2, spin2, xy);
  360.         y = xy[1];
  361.         break;
  362.       case 3:
  363.         /* pulsing circular */
  364.         if (1) {
  365.            double t = frame * 0.05;
  366.            double s = (sin(t * p->rhythm[0]) *
  367.                sin(t * p->rhythm[1]));
  368.            s = 1 - s * s;
  369.            x = (xy[0] - (XSIZE/2)) * s + (XSIZE/2);
  370.            y = (xy[1] - (YSIZE/2)) * s + (YSIZE/2);
  371.         }
  372.         break;
  373. #endif
  374.       case 1:
  375.         /* vertical */
  376.         /* y = (int)(0.987 * spinner_time * YSIZE) % YSIZE; */
  377.         y = (1+sin(spinner_time)) * (YSIZE/2);
  378.         break;
  379.      }
  380.      pen(dboard, p->mask, x, y, bsize);
  381.       }
  382.    } else {
  383.       for (bx = 0; bx < nbatches; bx++) {
  384.      int j, k;
  385.      double time = adjust_speed(p->drift_speed) * (bx/(double)nbatches) + p->drift_time;
  386.  
  387.      switch (drift_type) {
  388.      case 2:
  389.        for (i = 0; i < NXFORMS; i++) {
  390.          double r = 1e-6;
  391.          for (j = 0; j < 3; j++) {
  392.            for (k = 0; k < 2; k++) {
  393.          double x;
  394.          x = p->flame_cp.xform[i].c[j][k] +=
  395.            adjust_speed(cc_direction.xform[i].c[j][k]*0.1);
  396.          if (x > 1) cc_direction.xform[i].c[j][k] += -1e-3;
  397.          else if (x < -1) cc_direction.xform[i].c[j][k] += 1e-3;
  398.          else cc_direction.xform[i].c[j][k] += random_uniform11()*1e-3;
  399.            }
  400.          }
  401.        }
  402.          
  403.        break;
  404.      case 4:
  405.         for (i = 0; i < NXFORMS; i++)
  406.            for (j = 0; j < 3; j++)
  407.           for (k = 0; k < 2; k++)
  408.              p->flame_cp.xform[i].c[j][k] = sin(time * cc_direction.xform[i].c[j][k]);
  409.         break;
  410.       case 3:
  411.       case 5:
  412.         rotcp(p, adjust_speed(5.0 + p->drift_speed/20.0));
  413.         rot_point(p, adjust_speed(0.1));
  414.         break;
  415.       case 6:
  416.         rotcp(p, adjust_speed(0.03 + p->drift_speed/100.0));
  417.         break;
  418.       case 7:
  419.       case 8:
  420.         if (0) {
  421.           int i, j;
  422.           for (j = 0; j < flame_nspan; j++) {
  423.         p->flame_span[j].time = (double) j;
  424.         for (i = 0; i < 2; i++) {
  425.           p->flame_span[j].pulse[i][0] = 0.0;
  426.           p->flame_span[j].pulse[i][1] = 60.0;
  427.           p->flame_span[j].wiggle[i][0] = 0.0;
  428.           p->flame_span[j].wiggle[i][1] = 60.0;
  429.         }
  430.           }
  431.           interpolate(p->flame_span, flame_nspan, 1.1/*+0.02*sin(time)*/, &p->flame_cp);
  432.         }
  433.          
  434.         if (1) {
  435.            int c;
  436.            c = p->rhythm[0];
  437.            
  438.            rotcp(p, 20*adjust_speed(0.05 + sin(c*time/480.0)));
  439.            rot_point(p, 10*adjust_speed(sin(time/60.0)));
  440. #if 0
  441.            if (frame%c < c/2)
  442.           rotcp(p, adjust_speed(1.0));
  443.            else
  444.           rotcp(p, adjust_speed(-1.05));
  445.  
  446.            c = p->rhythm[1]/2;
  447.            if (frame%c < c/2)
  448.           rot_point(p, adjust_speed(0.5));
  449.            else
  450.           rot_point(p, adjust_speed(-0.5));
  451. #endif
  452.         }
  453.         break;
  454.       
  455.      }
  456.  
  457.      /* overhead of fuse could get in the way as bufsize drops, don't
  458.         really need it.  on fast rhythm mach, how small can batches go?
  459.         they are 100 now */
  460.      
  461.      iterate(&p->flame_cp, bufsize, 5, p_buf);
  462.      for (i = 0; i < bufsize; i++)  {
  463.         double px, py;
  464.         px = p_buf[i][0];
  465.         py = p_buf[i][1];
  466.         if (px < 1.0 && py < 1.0 && px > -1.0 && py > -1.0) {
  467.            int x, y;
  468.            x = (px + 1.0) * XSIZE/2;
  469.            y = (py + 1.0) * YSIZE/2;
  470.            pen(dboard, p->mask, x, y, bsize);
  471.         }
  472.      }
  473.       }
  474.    }
  475. #if 0
  476.    for (i = 0; i < nspinners; i++) {
  477.       printf("%d r=%g s=%g\n", i, SI.radius, SI.speed);
  478.    }
  479. #endif
  480. }
  481.  
  482.