home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / windows / winsrc.zip / LORENZ.C < prev    next >
Text File  |  1990-11-21  |  46KB  |  1,715 lines

  1. /*
  2.    This file contains two 3 dimensional orbit-type fractal
  3.    generators - IFS and LORENZ3D, along with code to generate
  4.    red/blue 3D images. Tim Wegner
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <float.h>
  10. #include "fractint.h"
  11. #include "fractype.h"
  12. struct affine
  13. {
  14.    /* weird order so a,b,e and c,d,f are vectors */
  15.    double a;
  16.    double b;
  17.    double e;
  18.    double c;
  19.    double d;
  20.    double f;
  21. };
  22.  
  23. /* Routines in this module    */
  24.  
  25. int  orbit3dlongsetup();
  26. int  orbit3dfloatsetup();
  27. int  lorenz3dlongorbit(long *, long *, long *);
  28. int  lorenz3dfloatorbit(double *, double *, double *);
  29. int  henonfloatorbit(double *, double *, double *);
  30. int  henonlongorbit(long *, long *, long *);
  31. int  rosslerfloatorbit(double *, double *, double *);
  32. int  pickoverfloatorbit(double *, double *, double *);
  33. int  gingerbreadfloatorbit(double *, double *, double *);
  34. int  rosslerlongorbit(long *, long *, long *);
  35. int  kamtorusfloatorbit(double *, double *, double *);
  36. int  kamtoruslongorbit(long *, long *, long *);
  37. int  orbit2dfloat(void);
  38. int  orbit2dlong(void);
  39. int  orbit3dlongcalc(void);
  40. int  orbit3dfloatcalc(void);
  41. int  funny_glasses_call(int (*calc)());
  42. int  ifs(void);
  43. int  orbit3dfloat(void);
  44. int  orbit3dlong(void);
  45. int  ifs3d(void);
  46.  
  47. static int  ifs3dlong(void);
  48. static int  ifs3dfloat(void);
  49. static double determinant(double mat[3][3]);
  50. static int  solve3x3(double mat[3][3],double vec[3],double ans[3]);
  51. static int  setup_convert_to_screen(struct affine *);
  52. static void setupmatrix(MATRIX);
  53.  
  54. static int realtime;
  55. extern int active_system;
  56. extern int overflow;
  57. extern int soundflag;
  58. extern int basehertz;
  59. extern int fractype;
  60. extern int glassestype;
  61. extern int whichimage;
  62. extern int init3d[];
  63. extern char floatflag;
  64. extern VECTOR view;
  65. extern int xxadjust, yyadjust;
  66. extern int xxadjust1, yyadjust1;
  67. extern int xshift,yshift;
  68. extern int xshift1,yshift1;
  69. extern void (*plot)();
  70. extern void (*standardplot)();
  71. extern int    debugflag;            /* for debugging purposes */
  72. extern int    xdots, ydots;        /* coordinates of dots on the screen  */
  73. extern int    maxit;                /* try this many iterations */
  74. extern double param[];
  75. extern double    xxmin,xxmax,yymin,yymax,xx3rd,yy3rd; /* selected screen corners  */
  76. extern    int    diskvideo;            /* for disk-video klooges */
  77. extern int    bitshift;            /* bit shift for fudge */
  78. extern long    fudge;                /* fudge factor (2**n) */
  79. extern int    colors;             /* maximum colors available */
  80.  
  81. extern int display3d;
  82. static int t;
  83. static long l_dx,l_dy,l_dz,l_dt,l_a,l_b,l_c,l_d;
  84. static long l_adt,l_bdt,l_cdt,l_xdt,l_ydt;
  85. static long l_initx,l_inity,l_initz;
  86. static long initorbitlong[3];
  87.  
  88. static double dx,dy,dz,dt,a,b,c,d;
  89. static double adt,bdt,cdt,xdt,ydt;
  90. static double initx,inity,initz;
  91. static double initorbit[3];
  92. extern int inside;
  93.  
  94. extern int  alloc_resume(int,int);
  95. extern int  start_resume();
  96. extern void end_resume();
  97. extern int  put_resume(int len, ...);
  98. extern int  get_resume(int len, ...);
  99. extern int  calc_status, resuming;
  100. extern int  diskisactive;
  101. extern int  resave_flag;
  102. extern char savename[];
  103.  
  104. /* these are potential user parameters */
  105. int connect = 1;    /* flag to connect points with a line */
  106. int waste = 100;    /* waste this many points before plotting */
  107. int projection = 2; /* projection plane - default is to plot x-y */
  108.  
  109. /******************************************************************/
  110. /*           zoom box conversion functions          */
  111. /******************************************************************/
  112.  
  113. static double determinant(mat) /* determinant of 3x3 matrix */
  114. double mat[3][3];
  115. {
  116.    /* calculate determinant of 3x3 matrix */
  117.    return(mat[0][0]*mat[1][1]*mat[2][2] +
  118.       mat[0][2]*mat[1][0]*mat[2][1] +
  119.       mat[0][1]*mat[1][2]*mat[2][0] -
  120.       mat[2][0]*mat[1][1]*mat[0][2] -
  121.       mat[1][0]*mat[0][1]*mat[2][2] -
  122.       mat[0][0]*mat[1][2]*mat[2][1]);
  123.  
  124. }
  125.  
  126. static int solve3x3(mat,vec,ans) /* solve 3x3 inhomogeneous linear equations */
  127. double mat[3][3], vec[3], ans[3];
  128. {
  129.    /* solve 3x3 linear equation [mat][ans] = [vec] */
  130.    double denom;
  131.    double tmp[3][3];
  132.    int i;
  133.    denom = determinant(mat);
  134.    if(fabs(denom) < DBL_EPSILON) /* test if can solve */
  135.      return(-1);
  136.    memcpy(tmp,mat,sizeof(double)*9);
  137.    for(i=0;i<3;i++)
  138.    {
  139.       tmp[0][i] = vec[0];
  140.       tmp[1][i] = vec[1];
  141.       tmp[2][i] = vec[2];
  142.       ans[i]  =  determinant(tmp)/denom;
  143.       tmp[0][i] = mat[0][i];
  144.       tmp[1][i] = mat[1][i];
  145.       tmp[2][i] = mat[2][i];
  146.     }
  147.     return(0);
  148. }
  149.  
  150.  
  151. /* Conversion of complex plane to screen coordinates for rotating zoom box.
  152.    Assume there is an affine transformation mapping complex zoom parallelogram
  153.    to rectangular screen. We know this map must map parallelogram corners to
  154.    screen corners, so we have following equations:
  155.  
  156.       a*xxmin+b*yymax+e == 0        (upper left)
  157.       c*xxmin+d*yymax+f == 0
  158.  
  159.       a*xx3rd+b*yy3rd+e == 0        (lower left)
  160.       c*xx3rd+d*yy3rd+f == ydots-1
  161.  
  162.       a*xxmax+b*yymin+e == xdots-1  (lower right)
  163.       c*xxmax+d*yymin+f == ydots-1
  164.  
  165.       First we must solve for a,b,c,d,e,f - (which we do once per image),
  166.       then we just apply the transformation to each orbit value.
  167. */
  168.  
  169. static int setup_convert_to_screen(struct affine *scrn_cnvt)
  170. {
  171.    /* we do this twice - rather than having six equations with six unknowns,
  172.       everything partitions to two sets of three equations with three
  173.       unknowns. Nice, because who wants to calculate a 6x6 determinant??
  174.     */
  175.    double mat[3][3];
  176.    double vec[3];
  177.    /*
  178.       first these equations - solve for a,b,e
  179.       a*xxmin+b*yymax+e == 0        (upper left)
  180.       a*xx3rd+b*yy3rd+e == 0        (lower left)
  181.       a*xxmax+b*yymin+e == xdots-1  (lower right)
  182.    */
  183.    mat[0][0] = xxmin;
  184.    mat[0][1] = yymax;
  185.    mat[0][2] = 1.0;
  186.    mat[1][0] = xx3rd;
  187.    mat[1][1] = yy3rd;
  188.    mat[1][2] = 1.0;
  189.    mat[2][0] = xxmax;
  190.    mat[2][1] = yymin;
  191.    mat[2][2] = 1.0;
  192.    vec[0]    = 0.0;
  193.    vec[1]    = 0.0;
  194.    vec[2]    = (double)(xdots-1);
  195.  
  196.    if(solve3x3(mat,vec, &(scrn_cnvt->a)))
  197.       return(-1);
  198.    /*
  199.       now solve these:
  200.       c*xxmin+d*yymax+f == 0
  201.       c*xx3rd+d*yy3rd+f == ydots-1
  202.       c*xxmax+d*yymin+f == ydots-1
  203.       (mat[][] has not changed - only vec[])
  204.    */
  205.    vec[0]    = 0.0;
  206.    vec[1]    = (double)(ydots-1);
  207.    vec[2]    = (double)(ydots-1);
  208.  
  209.    if(solve3x3(mat,vec, &scrn_cnvt->c))
  210.       return(-1);
  211.    return(0);
  212. }
  213.  
  214. /******************************************************************/
  215. /*   setup functions - put in fractalspecific[fractype].per_image */
  216. /******************************************************************/
  217.  
  218. double orbit;
  219. long   l_orbit;
  220.  
  221. extern double sinx,cosx;
  222. long l_sinx,l_cosx;
  223.  
  224. int orbit3dlongsetup()
  225. {
  226.    connect = 1;
  227.    waste = 100;
  228.    projection = 2;
  229.    if(fractype==LHENON || fractype==KAM || fractype==KAM3D)
  230.       connect=0;
  231.    if(fractype==LROSSLER)
  232.       waste = 500;
  233.    if(fractype==LLORENZ)
  234.       projection = 1;
  235.  
  236.    initorbitlong[0] = fudge;  /* initial conditions */
  237.    initorbitlong[1] = fudge;
  238.    initorbitlong[2] = fudge;
  239.  
  240.    if(fractype==LHENON)
  241.    {
  242.       l_a =  param[0]*fudge;
  243.       l_b =  param[1]*fudge;
  244.       l_c =  param[2]*fudge;
  245.       l_d =  param[3]*fudge;
  246.    }
  247.    else if(fractype==KAM || fractype==KAM3D)
  248.    {
  249.       a   = param[0];        /* angle */
  250.       if(param[1] <= 0.0)
  251.      param[1] = .01;
  252.       l_b =  param[1]*fudge;    /* stepsize */
  253.       l_c =  param[2]*fudge;    /* stop */
  254.       t = l_d =  param[3];     /* points per orbit */
  255.  
  256.       l_sinx = sin(a)*fudge;
  257.       l_cosx = cos(a)*fudge;
  258.       l_orbit = 0;
  259.       initorbitlong[0] = initorbitlong[1] = initorbitlong[2] = 0;
  260.    }
  261.    else
  262.    {
  263.       l_dt = param[0]*fudge;
  264.       l_a =  param[1]*fudge;
  265.       l_b =  param[2]*fudge;
  266.       l_c =  param[3]*fudge;
  267.    }
  268.  
  269.    /* precalculations for speed */
  270.    l_adt = multiply(l_a,l_dt,bitshift);
  271.    l_bdt = multiply(l_b,l_dt,bitshift);
  272.    l_cdt = multiply(l_c,l_dt,bitshift);
  273.    return(1);
  274. }
  275.  
  276.  
  277.  
  278. int orbit3dfloatsetup()
  279. {
  280.    connect = 1;
  281.    waste = 100;
  282.    projection = 2;
  283.  
  284.    if(fractype==FPHENON || fractype==FPPICKOVER || fractype==FPGINGERBREAD
  285.         || fractype == KAMFP || fractype == KAM3DFP)
  286.       connect=0;
  287.    if(fractype==FPROSSLER)
  288.       waste = 500;
  289.    if(fractype==FPLORENZ)
  290.       projection = 1; /* plot x and z */
  291.  
  292.    initorbit[0] = 1;  /* initial conditions */
  293.    initorbit[1] = 1;
  294.    initorbit[2] = 1;
  295.    if(fractype==FPGINGERBREAD)
  296.    {
  297.       initorbit[0] = -.1;  /* initial conditions */
  298.       initorbit[1] = 0;
  299.    }
  300.    if(fractype==FPHENON || fractype==FPPICKOVER)
  301.    {
  302.       a =  param[0];
  303.       b =  param[1];
  304.       c =  param[2];
  305.       d =  param[3];
  306.    }
  307.    else if(fractype==KAMFP || fractype==KAM3DFP)
  308.    {
  309.       a = param[0];          /* angle */
  310.       if(param[1] <= 0.0)
  311.      param[1] = .01;
  312.       b =  param[1];    /* stepsize */
  313.       c =  param[2];    /* stop */
  314.       t = l_d =  param[3];     /* points per orbit */
  315.       sinx = sin(a);
  316.       cosx = cos(a);
  317.       orbit = 0;
  318.       initorbit[0] = initorbit[1] = initorbit[2] = 0;
  319.    }
  320.    else
  321.    {
  322.       dt = param[0];
  323.       a =  param[1];
  324.       b =  param[2];
  325.       c =  param[3];
  326.    }
  327.  
  328.    /* precalculations for speed */
  329.    adt = a*dt;
  330.    bdt = b*dt;
  331.    cdt = c*dt;
  332.  
  333.    return(1);
  334. }
  335.  
  336. /******************************************************************/
  337. /*   orbit functions - put in fractalspecific[fractype].orbitcalc */
  338. /******************************************************************/
  339.  
  340. int lorenz3dlongorbit(long *l_x, long *l_y, long *l_z)
  341. {
  342.       l_xdt = multiply(*l_x,l_dt,bitshift);
  343.       l_ydt = multiply(*l_y,l_dt,bitshift);
  344.       l_dx  = -multiply(l_adt,*l_x,bitshift) + multiply(l_adt,*l_y,bitshift);
  345.       l_dy  =  multiply(l_bdt,*l_x,bitshift) -l_ydt -multiply(*l_z,l_xdt,bitshift);
  346.       l_dz  = -multiply(l_cdt,*l_z,bitshift) + multiply(*l_x,l_ydt,bitshift);
  347.  
  348.       *l_x += l_dx;
  349.       *l_y += l_dy;
  350.       *l_z += l_dz;
  351.       return(0);
  352. }
  353.  
  354. int lorenz3dfloatorbit(double *x, double *y, double *z)
  355. {
  356.       xdt = (*x)*dt;
  357.       ydt = (*y)*dt;
  358.       dx  = -adt*(*x) + adt*(*y);
  359.       dy  =  bdt*(*x) - ydt - (*z)*xdt;
  360.       dz  = -cdt*(*z) + (*x)*ydt;
  361.  
  362.       *x += dx;
  363.       *y += dy;
  364.       *z += dz;
  365.       return(0);
  366. }
  367.  
  368. int henonfloatorbit(double *x, double *y, double *z)
  369. {
  370.       double newx,newy;
  371.       newx  = 1 + *y - a*(*x)*(*x);
  372.       newy  = b*(*x);
  373.       *x = newx;
  374.       *y = newy;
  375.       return(0);
  376. }
  377.  
  378. int henonlongorbit(long *l_x, long *l_y, long *l_z)
  379. {
  380.       long newx,newy;
  381.       newx = multiply(*l_x,*l_x,bitshift);
  382.       newx = multiply(newx,l_a,bitshift);
  383.       newx  = fudge + *l_y - newx;
  384.       newy  = multiply(l_b,*l_x,bitshift);
  385.       *l_x = newx;
  386.       *l_y = newy;
  387.       return(0);
  388. }
  389.  
  390. int rosslerfloatorbit(double *x, double *y, double *z)
  391. {
  392.       xdt = (*x)*dt;
  393.       ydt = (*y)*dt;
  394.  
  395.       dx = -ydt - (*z)*dt;
  396.       dy = xdt + (*y)*adt;
  397.       dz = bdt + (*z)*xdt - (*z)*cdt;
  398.  
  399.       *x += dx;
  400.       *y += dy;
  401.       *z += dz;
  402.       return(0);
  403. }
  404.  
  405. int pickoverfloatorbit(double *x, double *y, double *z)
  406. {
  407.       double newx,newy,newz;
  408.       newx = sin(a*(*y)) - (*z)*cos(b*(*x));
  409.       newy = (*z)*sin(c*(*x)) - cos(d*(*y));
  410.       newz = sin(*x);
  411.       *x = newx;
  412.       *y = newy;
  413.       *z = newz;
  414.       return(0);
  415. }
  416. /* page 149 "Science of Fractal Images" */
  417. int gingerbreadfloatorbit(double *x, double *y, double *z)
  418. {
  419.       double newx;
  420.       newx = 1 - (*y) + fabs(*x);
  421.       *y = *x;
  422.       *x = newx;
  423.       return(0);
  424. }
  425.  
  426. int rosslerlongorbit(long *l_x, long *l_y, long *l_z)
  427. {
  428.       l_xdt = multiply(*l_x,l_dt,bitshift);
  429.       l_ydt = multiply(*l_y,l_dt,bitshift);
  430.  
  431.       l_dx  = -l_ydt - multiply(*l_z,l_dt,bitshift);
  432.       l_dy  =  l_xdt + multiply(*l_y,l_adt,bitshift);
  433.       l_dz  =  l_bdt + multiply(*l_z,l_xdt,bitshift)
  434.              - multiply(*l_z,l_cdt,bitshift);
  435.  
  436.       *l_x += l_dx;
  437.       *l_y += l_dy;
  438.       *l_z += l_dz;
  439.  
  440.       return(0);
  441. }
  442.  
  443. /* OSTEP  = Orbit Step (and inner orbit value) */
  444. /* NTURNS = Outside Orbit */
  445. /* TURN2  = Points per orbit */
  446. /* a      = Angle */
  447.  
  448.  
  449. int kamtorusfloatorbit(double *r, double *s, double *z)
  450. {
  451.    double srr;
  452.    if(t++ >= l_d)
  453.    {
  454.       orbit += b;
  455.       (*r) = (*s) = orbit/3;
  456.       t = 0;
  457.       *z = orbit;
  458.       if(orbit > c)
  459.      return(1);
  460.    }
  461.    srr = (*s)-(*r)*(*r);
  462.    (*s)=(*r)*sinx+srr*cosx;
  463.    (*r)=(*r)*cosx-srr*sinx;
  464.    return(0);
  465. }
  466.  
  467. int kamtoruslongorbit(long *r, long *s, long *z)
  468. {
  469.    long srr;
  470.    if(t++ >= l_d)
  471.    {
  472.       l_orbit += l_b;
  473.       (*r) = (*s) = l_orbit/3;
  474.       t = 0;
  475.       *z = l_orbit;
  476.       if(l_orbit > l_c)
  477.      return(1);
  478.    }
  479.    srr = (*s)-multiply((*r),(*r),bitshift);
  480.    (*s)=multiply((*r),l_sinx,bitshift)+multiply(srr,l_cosx,bitshift);
  481.    (*r)=multiply((*r),l_cosx,bitshift)-multiply(srr,l_sinx,bitshift);
  482.    return(0);
  483. }
  484.  
  485.  
  486. /**********************************************************************/
  487. /*   Main fractal engines - put in fractalspecific[fractype].calctype */
  488. /**********************************************************************/
  489.  
  490. int orbit2dfloat()
  491. {
  492.    double *soundvar;
  493.    double x,y,z;
  494.    int color,col,row;
  495.    int count;
  496.    int oldrow, oldcol;
  497.    double *p0,*p1,*p2;
  498.    struct affine cvt;
  499.  
  500.    /* setup affine screen coord conversion */
  501.    setup_convert_to_screen(&cvt);
  502.  
  503.    /* set up projection scheme */
  504.    if(projection==0)
  505.    {
  506.       p0 = &z;
  507.       p1 = &x;
  508.       p2 = &y;
  509.    }
  510.    else if(projection==1)
  511.    {
  512.       p0 = &x;
  513.       p1 = &z;
  514.       p2 = &y;
  515.    }
  516.    else if(projection==2)
  517.    {
  518.       p0 = &x;
  519.       p1 = &y;
  520.       p2 = &z;
  521.    }
  522.    if(soundflag==1)
  523.       soundvar = &x;
  524.    else if(soundflag==2)
  525.       soundvar = &y;
  526.    else if(soundflag==3)
  527.       soundvar = &z;
  528.  
  529.    count = 0;
  530.    if(inside > 0)
  531.       color = inside;
  532.    if(color >= colors)
  533.       color = 1;
  534.    oldcol = oldrow = -1;
  535.    x = initorbit[0];
  536.    y = initorbit[1];
  537.    z = initorbit[2];
  538.  
  539.    if (resuming)
  540.    {
  541.       start_resume();
  542.       get_resume(sizeof(count),&count,sizeof(color),&color,
  543.          sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  544.          sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,
  545.          sizeof(t),&t,sizeof(orbit),&orbit,
  546.          0);
  547.       end_resume();
  548.    }
  549.  
  550.    while(1)
  551.    {
  552.       if(check_key())
  553.       {
  554.          nosnd();
  555.          alloc_resume(100,1);
  556.          put_resume(sizeof(count),&count,sizeof(color),&color,
  557.             sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  558.             sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,
  559.             sizeof(t),&t,sizeof(orbit),&orbit,
  560.             0);
  561.          return(-1);
  562.       }
  563.  
  564.       if (++count > 1000)
  565.       {        /* time to switch colors? */
  566.      count = 0;
  567.      if (++color >= colors)   /* another color to switch to? */
  568.           color = 1;    /* (don't use the background color) */
  569.       }
  570.  
  571.       col = cvt.a*x + cvt.b*y + cvt.e;
  572.       row = cvt.c*x + cvt.d*y + cvt.f;
  573.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  574.       {
  575.      if (soundflag > 0)
  576.        snd((int)(*soundvar*100+basehertz));
  577.  
  578.      if(oldcol != -1 && connect)
  579.         draw_line(col,row,oldcol,oldrow,color&(colors-1));
  580.      else
  581.         (*plot)(col,row,color&(colors-1));
  582.      oldcol = col;
  583.      oldrow = row;
  584.       }
  585.       else
  586.      oldrow = oldcol = -1;
  587.  
  588.       if(fractalspecific[fractype].orbitcalc(p0, p1, p2))
  589.      break;
  590.    }
  591.    return(0);
  592. }
  593.  
  594. int orbit2dlong()
  595. {
  596.    long a,b,c,d,e,f;
  597.    long *soundvar;
  598.    long x,y,z;
  599.    int color,col,row;
  600.    int count;
  601.    int oldrow, oldcol;
  602.    long *p0,*p1,*p2;
  603.    struct affine cvt;
  604.  
  605.    /* setup affine screen coord conversion */
  606.    setup_convert_to_screen(&cvt);
  607.    a = cvt.a*fudge; b = cvt.b*fudge; c = cvt.c*fudge;
  608.    d = cvt.d*fudge; e = cvt.e*fudge; f = cvt.f*fudge;
  609.  
  610.    /* set up projection scheme */
  611.    if(projection==0)
  612.    {
  613.       p0 = &z;
  614.       p1 = &x;
  615.       p2 = &y;
  616.    }
  617.    else if(projection==1)
  618.    {
  619.       p0 = &x;
  620.       p1 = &z;
  621.       p2 = &y;
  622.    }
  623.    else if(projection==2)
  624.    {
  625.       p0 = &x;
  626.       p1 = &y;
  627.       p2 = &z;
  628.    }
  629.    if(soundflag==1)
  630.       soundvar = &x;
  631.    else if(soundflag==2)
  632.       soundvar = &y;
  633.    else if(soundflag==3)
  634.       soundvar = &z;
  635.    count = 0;
  636.    if(inside > 0)
  637.       color = inside;
  638.    if(color >= colors)
  639.       color = 1;
  640.    oldcol = oldrow = -1;
  641.    x = initorbitlong[0];
  642.    y = initorbitlong[1];
  643.    z = initorbitlong[2];
  644.  
  645.    if (resuming)
  646.    {
  647.       start_resume();
  648.       get_resume(sizeof(count),&count,sizeof(color),&color,
  649.          sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  650.          sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,
  651.          sizeof(t),&t,sizeof(l_orbit),&l_orbit,
  652.          0);
  653.       end_resume();
  654.    }
  655.  
  656.    while(1)
  657.    {
  658.       if(check_key())
  659.       {
  660.      nosnd();
  661.      alloc_resume(100,1);
  662.      put_resume(sizeof(count),&count,sizeof(color),&color,
  663.             sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  664.             sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,
  665.             sizeof(t),&t,sizeof(l_orbit),&l_orbit,
  666.             0);
  667.      return(-1);
  668.       }
  669.       if (++count > 1000)
  670.       {        /* time to switch colors? */
  671.      count = 0;
  672.      if (++color >= colors)   /* another color to switch to? */
  673.           color = 1;    /* (don't use the background color) */
  674.       }
  675.  
  676.       col = (multiply(a,x,bitshift) + multiply(b,y,bitshift) + e) >> bitshift;
  677.       row = (multiply(c,x,bitshift) + multiply(d,y,bitshift) + f) >> bitshift;
  678.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  679.       {
  680.      if (soundflag > 0)
  681.      {
  682.         double yy;
  683.         yy = *soundvar;
  684.         yy = yy/fudge;
  685.         snd((int)(yy*100+basehertz));
  686.      }
  687.      if(oldcol != -1 && connect)
  688.         draw_line(col,row,oldcol,oldrow,color&(colors-1));
  689.      else
  690.         (*plot)(col,row,color&(colors-1));
  691.      oldcol = col;
  692.      oldrow = row;
  693.       }
  694.       else
  695.      oldrow = oldcol = -1;
  696.  
  697.       /* Calculate the next point */
  698.       if(fractalspecific[fractype].orbitcalc(p0, p1, p2))
  699.      break;
  700.    }
  701.    return(0);
  702. }
  703.  
  704. int orbit3dlongcalc()
  705. {
  706.    long a,b,c,d,e,f;
  707.    unsigned count;
  708.    int oldcol,oldrow;
  709.    int oldcol1,oldrow1;
  710.  
  711.    double tmpx, tmpy, tmpz;
  712.    long iview[3];      /* perspective viewer's coordinates */
  713.  
  714.    long tmp;
  715.    long maxvals[3];
  716.    long minvals[3];
  717.    unsigned long maxct,ct;
  718.    register int col;
  719.    register int row;
  720.    register int color;
  721.  
  722.    int i,j,k;
  723.  
  724.    /* 3D viewing stuff */
  725.    MATRIX doublemat;           /* transformation matrix */
  726.    MATRIX doublemat1;        /* transformation matrix */
  727.    long longmat[4][4];           /* long version of matrix */
  728.    long longmat1[4][4];     /* long version of matrix */
  729.    long orbit[3];           /* interated function orbit value */
  730.    long viewvect[3];        /* orbit transformed for viewing */
  731.    long viewvect1[3];         /* orbit transformed for viewing */
  732.  
  733.    struct affine cvt;
  734.  
  735.    /* setup affine screen coord conversion */
  736.    setup_convert_to_screen(&cvt);
  737.    a = cvt.a*fudge; b = cvt.b*fudge; c = cvt.c*fudge;
  738.    d = cvt.d*fudge; e = cvt.e*fudge; f = cvt.f*fudge;
  739.  
  740.    oldcol1 = oldrow1 = oldcol = oldrow = -1;
  741.    color = 2;
  742.    if(color >= colors)
  743.       color = 1;
  744.  
  745.    orbit[0] = initorbitlong[0];
  746.    orbit[1] = initorbitlong[1];
  747.    orbit[2] = initorbitlong[2];
  748.  
  749.    for(i=0;i<3;i++)
  750.    {
  751.       minvals[i] =  1L << 30;
  752.       maxvals[i] = -minvals[i];
  753.    }
  754.  
  755.    setupmatrix(doublemat);
  756.    if(realtime)
  757.       setupmatrix(doublemat1);
  758.  
  759.    /* copy xform matrix to long for for fixed point math */
  760.    for (i = 0; i < 4; i++)
  761.       for (j = 0; j < 4; j++)
  762.       {
  763.      longmat[i][j] = doublemat[i][j] * fudge;
  764.      if(realtime)
  765.         longmat1[i][j] = doublemat1[i][j] * fudge;
  766.       }
  767.    if(diskvideo)        /* this would KILL a disk drive! */
  768.    {
  769.       notdiskmsg();
  770.       return(-1);
  771.    }
  772.  
  773.    /* make maxct a function of screen size         */
  774.    maxct = maxit*40L;
  775.    count = ct = 0L;
  776.    while(ct++ < maxct) /* loop until keypress or maxit */
  777.    {
  778.       /* calc goes here */
  779.       if (++count > 1000)
  780.       {        /* time to switch colors? */
  781.      count = 0;
  782.      if (++color >= colors)   /* another color to switch to? */
  783.         color = 1;          /* (don't use the background color) */
  784.       }
  785.       if(check_key())
  786.       {
  787.      nosnd();
  788.      return(-1);
  789.       }
  790.  
  791.       fractalspecific[fractype].orbitcalc(&orbit[0],&orbit[1],&orbit[2]);
  792.  
  793.       /* 3D VIEWING TRANSFORM */
  794.       longvmult(orbit,longmat,viewvect, bitshift);
  795.       if(realtime)
  796.      longvmult(orbit,longmat1,viewvect1, bitshift);
  797.  
  798.       if(ct <= waste) /* waste this many points to find minz and maxz */
  799.       {
  800.      /* find minz and maxz */
  801.      for(i=0;i<3;i++)
  802.         if ((tmp = viewvect[i]) < minvals[i])
  803.            minvals[i] = tmp;
  804.         else if (tmp > maxvals[i])
  805.            maxvals[i] = tmp;
  806.      if(ct == waste)
  807.      {
  808.         iview[0] = iview[1] = 0L; /* center viewer on origin */
  809.  
  810.         /* z value of user's eye - should be more negative than extreme
  811.                negative part of image */
  812.         iview[2] = (long)((minvals[2]-maxvals[2])*(double)ZVIEWER/100.0);
  813.  
  814.         /* center image on origin */
  815.         tmpx = (-minvals[0]-maxvals[0])/(2.0*fudge); /* center x */
  816.         tmpy = (-minvals[1]-maxvals[1])/(2.0*fudge); /* center y */
  817.  
  818.         /* apply perspective shift */
  819.         tmpx += ((double)xshift*(xxmax-xxmin))/(xdots)  ;
  820.         tmpy += ((double)yshift*(yymax-yymin))/(ydots);
  821.         tmpz = -((double)maxvals[2]);
  822.         tmpz /= fudge;
  823.         trans(tmpx,tmpy,tmpz,doublemat);
  824.  
  825.         if(realtime)
  826.         {
  827.            /* center image on origin */
  828.            tmpx = (-minvals[0]-maxvals[0])/(2.0*fudge); /* center x */
  829.            tmpy = (-minvals[1]-maxvals[1])/(2.0*fudge); /* center y */
  830.  
  831.            tmpx += ((double)xshift1*(xxmax-xxmin))/(xdots);
  832.            tmpy += ((double)yshift1*(yymax-yymin))/(ydots);
  833.            tmpz = -((double)maxvals[2]);
  834.            tmpz /= fudge;
  835.            trans(tmpx,tmpy,tmpz,doublemat1);
  836.         }
  837.         for(i=0;i<3;i++)
  838.         {
  839.            view[i] = iview[i];
  840.            view[i] /= fudge;
  841.         }
  842.  
  843.         /* copy xform matrix to long for for fixed point math */
  844.         for (i = 0; i < 4; i++)
  845.            for (j = 0; j < 4; j++)
  846.            {
  847.           longmat[i][j] = doublemat[i][j] * fudge;
  848.           if(realtime)
  849.              longmat1[i][j] = doublemat1[i][j] * fudge;
  850.            }
  851.      }
  852.       }
  853.  
  854.       if(ct > waste)
  855.       {
  856.      /* apply perspective if requested */
  857.      if(ZVIEWER)
  858.      {
  859.         if(debugflag==22 || ZVIEWER < 100) /* use float for small persp */
  860.         {
  861.            /* use float perspective calc */
  862.            VECTOR tmpv;
  863.            for(i=0;i<3;i++)
  864.            {
  865.           tmpv[i] = viewvect[i];
  866.           tmpv[i] /= fudge;
  867.            }
  868.            perspective(tmpv);
  869.            for(i=0;i<3;i++)
  870.           viewvect[i] = tmpv[i]*fudge;
  871.            if(realtime)
  872.            {
  873.           for(i=0;i<3;i++)
  874.           {
  875.              tmpv[i] = viewvect1[i];
  876.              tmpv[i] /= fudge;
  877.           }
  878.           perspective(tmpv);
  879.           for(i=0;i<3;i++)
  880.              viewvect1[i] = tmpv[i]*fudge;
  881.            }
  882.         }
  883.         else
  884.         {
  885.            longpersp(viewvect,iview,bitshift);
  886.            if(realtime)
  887.           longpersp(viewvect1,iview,bitshift);
  888.         }
  889.      }
  890.      if(realtime)
  891.         whichimage=1;
  892.      /* plot if inside window */
  893.      col = (multiply(a,viewvect[0],bitshift)+
  894.         multiply(b,viewvect[1],bitshift)+e) >> bitshift;
  895.      row = (multiply(c,viewvect[0],bitshift)+
  896.         multiply(d,viewvect[1],bitshift)+f) >> bitshift;
  897.      col += xxadjust;
  898.      row += yyadjust;
  899.      if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  900.      {
  901.         if (soundflag > 0)
  902.         {
  903.            double yy;
  904.            yy = viewvect[soundflag-1];
  905.            yy = yy/fudge;
  906.            snd((int)(yy*100+basehertz));
  907.         }
  908.         if(oldcol != -1 && connect)
  909.            draw_line(col,row,oldcol,oldrow,color&(colors-1));
  910.         else
  911.            (*plot)(col,row,color&(colors-1));
  912.         oldcol = col;
  913.         oldrow = row;
  914.      }
  915.      else
  916.         oldrow = oldcol = -1;
  917.      if(realtime)
  918.      {
  919.         whichimage=2;
  920.         /* plot if inside window */
  921.         col = (multiply(a,viewvect1[0],bitshift)+
  922.            multiply(b,viewvect1[1],bitshift)+e) >> bitshift;
  923.         row = (multiply(c,viewvect1[0],bitshift)+
  924.            multiply(d,viewvect1[1],bitshift)+f) >> bitshift;
  925.         col += xxadjust1;
  926.         row += yyadjust1;
  927.  
  928.         if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  929.         {
  930.            if(oldcol1 != -1 && connect)
  931.           draw_line(col,row,oldcol1,oldrow1,color&(colors-1));
  932.            else
  933.           (*plot)(col,row,color&(colors-1));
  934.            oldcol1 = col;
  935.            oldrow1 = row;
  936.         }
  937.         else
  938.            oldrow1 = oldcol1 = -1;
  939.      }
  940.       }
  941.    }
  942.    return(0);
  943. }
  944.  
  945.  
  946. int orbit3dfloatcalc()
  947. {
  948.    unsigned count;
  949.    int oldcol,oldrow;
  950.    int oldcol1,oldrow1;
  951.  
  952.    double tmpx, tmpy, tmpz;
  953.    extern VECTOR view;
  954.    double tmp;
  955.    double maxvals[3];
  956.    double minvals[3];
  957.    extern int init3d[];
  958.    unsigned long maxct,ct;
  959.    register int col;
  960.    register int row;
  961.    register int color;
  962.  
  963.  
  964.    int i,j,k;
  965.  
  966.    /* 3D viewing stuff */
  967.    MATRIX doublemat;           /* transformation matrix */
  968.    MATRIX doublemat1;        /* transformation matrix */
  969.    double orbit[3];           /* interated function orbit value */
  970.    double viewvect[3];          /* orbit transformed for viewing */
  971.    double viewvect1[3];        /* orbit transformed for viewing */
  972.    struct affine cvt;
  973.  
  974.    /* setup affine screen coord conversion */
  975.    setup_convert_to_screen(&cvt);
  976.  
  977.    oldcol = oldrow = -1;
  978.    oldcol1 = oldrow1 = -1;
  979.    color = 2;
  980.    if(color >= colors)
  981.       color = 1;
  982.    orbit[0] = initorbit[0];
  983.    orbit[1] = initorbit[1];
  984.    orbit[2] = initorbit[2];
  985.  
  986.    for(i=0;i<3;i++)
  987.    {
  988.       minvals[i] =  100000.0; /* impossible value */
  989.       maxvals[i] = -100000.0;
  990.    }
  991.  
  992.    setupmatrix(doublemat);
  993.    if(realtime)
  994.       setupmatrix(doublemat1);
  995.  
  996.    if(diskvideo)        /* this would KILL a disk drive! */
  997.    {
  998.       notdiskmsg();
  999.       return(-1);
  1000.    }
  1001.  
  1002.    maxct = maxit*40L;
  1003.    count = ct = 0L;
  1004.    while(ct++ < maxct) /* loop until keypress or maxit */
  1005.    {
  1006.       /* calc goes here */
  1007.       if (++count > 1000)
  1008.       {        /* time to switch colors? */
  1009.      count = 0;
  1010.      if (++color >= colors)   /* another color to switch to? */
  1011.         color = 1;          /* (don't use the background color) */
  1012.       }
  1013.  
  1014.       if(check_key())
  1015.       {
  1016.      nosnd();
  1017.      return(-1);
  1018.       }
  1019.  
  1020.       fractalspecific[fractype].orbitcalc(&orbit[0],&orbit[1],&orbit[2]);
  1021.  
  1022.       /* 3D VIEWING TRANSFORM */
  1023.       vmult(orbit,doublemat,viewvect );
  1024.       if(realtime)
  1025.      vmult(orbit,doublemat1,viewvect1);
  1026.  
  1027.       if(ct <= waste) /* waste this many points to find minz and maxz */
  1028.       {
  1029.      /* find minz and maxz */
  1030.      for(i=0;i<3;i++)
  1031.         if ((tmp = viewvect[i]) < minvals[i])
  1032.            minvals[i] = tmp;
  1033.         else if (tmp > maxvals[i])
  1034.            maxvals[i] = tmp;
  1035.      if(ct == waste)
  1036.      {
  1037.         view[0] = view[1] = 0; /* center on origin */
  1038.         /* z value of user's eye - should be more negative than extreme
  1039.                negative part of image */
  1040.         view[2] = (minvals[2]-maxvals[2])*(double)ZVIEWER/100.0;
  1041.  
  1042.         /* center image on origin */
  1043.         tmpx = (-minvals[0]-maxvals[0])/(2.0); /* center x */
  1044.         tmpy = (-minvals[1]-maxvals[1])/(2.0); /* center y */
  1045.  
  1046.         /* apply perspective shift */
  1047.         tmpx += ((double)xshift*(xxmax-xxmin))/(xdots)  ;
  1048.         tmpy += ((double)yshift*(yymax-yymin))/(ydots);
  1049.         tmpz = -((double)maxvals[2]);
  1050.         trans(tmpx,tmpy,tmpz,doublemat);
  1051.  
  1052.         if(realtime)
  1053.         {
  1054.            /* center image on origin */
  1055.            tmpx = (-minvals[0]-maxvals[0])/(2.0); /* center x */
  1056.            tmpy = (-minvals[1]-maxvals[1])/(2.0); /* center y */
  1057.  
  1058.            tmpx += ((double)xshift1*(xxmax-xxmin))/(xdots);
  1059.            tmpy += ((double)yshift1*(yymax-yymin))/(ydots);
  1060.            tmpz = -((double)maxvals[2]);
  1061.            trans(tmpx,tmpy,tmpz,doublemat1);
  1062.         }
  1063.      }
  1064.       }
  1065.  
  1066.       if(ct > waste)
  1067.       {
  1068.      /* apply perspective if requested */
  1069.      if(ZVIEWER)
  1070.      {
  1071.         perspective(viewvect);
  1072.         if(realtime)
  1073.            perspective(viewvect1);
  1074.      }
  1075.      if(realtime)
  1076.         whichimage=1;
  1077.      /* plot if inside window */
  1078.      col = cvt.a*viewvect[0] + cvt.b*viewvect[1] + cvt.e + xxadjust;
  1079.      row = cvt.c*viewvect[0] + cvt.d*viewvect[1] + cvt.f + yyadjust;
  1080.      if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  1081.      {
  1082.         if (soundflag > 0)
  1083.            snd((int)(viewvect[soundflag-1]*100+basehertz));
  1084.         if(oldcol != -1 && connect)
  1085.            draw_line(col,row,oldcol,oldrow,color&(colors-1));
  1086.         else
  1087.            (*plot)(col,row,color&(colors-1));
  1088.         oldcol = col;
  1089.         oldrow = row;
  1090.      }
  1091.      else
  1092.         oldrow = oldcol = -1;
  1093.      if(realtime)
  1094.      {
  1095.         whichimage=2;
  1096.         /* plot if inside window */
  1097.         col = cvt.a*viewvect1[0] + cvt.b*viewvect1[1] + cvt.e + xxadjust1;
  1098.         row = cvt.c*viewvect1[0] + cvt.d*viewvect1[1] + cvt.f + yyadjust1;
  1099.         if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  1100.         {
  1101.            if(oldcol1 != -1 && connect)
  1102.           draw_line(col,row,oldcol1,oldrow1,color&(colors-1));
  1103.            else
  1104.           (*plot)(col,row,color&(colors-1));
  1105.            oldcol1 = col;
  1106.            oldrow1 = row;
  1107.         }
  1108.         else
  1109.            oldrow1 = oldcol1 = -1;
  1110.      }
  1111.       }
  1112.    }
  1113.    return(0);
  1114. }
  1115.  
  1116. /* this function's only purpose is to manage funnyglasses related */
  1117. /* stuff so the code is not duplicated for ifs3d() and lorenz3d() */
  1118. int funny_glasses_call(int (*calc)())
  1119. {
  1120.    int status;
  1121.    status = 0;
  1122.    if(glassestype)
  1123.       whichimage = 1;
  1124.    else
  1125.       whichimage = 0;
  1126.    plot_setup();
  1127.    plot = standardplot;
  1128.    status = calc();
  1129.    if(realtime && glassestype != 3)
  1130.    {
  1131.       realtime = 0;
  1132.       return(status);
  1133.    }
  1134.    if(glassestype && status == 0 && display3d)
  1135.    {
  1136.       if(glassestype==3) /* photographer's mode */
  1137.      if(active_system == 0) { /* dos version */
  1138.         int i;
  1139. static char far firstready[]={"\
  1140. First image (left eye) is ready.  Hit any key to see it,\n\
  1141. then hit <s> to save, hit any other key to create second image."};
  1142.         stopmsg(16,firstready);
  1143.         while ((i = getakey()) == 's' || i == 'S') {
  1144.            if (resave_flag == 2)
  1145.           resave_flag = 0;
  1146.            diskisactive = 1;
  1147.            savetodisk(savename);
  1148.            diskisactive = 0;
  1149.            }
  1150.         /* is there a better way to clear the screen in graphics mode? */
  1151.         setvideomode(videoentry.videomodeax,
  1152.         videoentry.videomodebx,
  1153.         videoentry.videomodecx,
  1154.         videoentry.videomodedx);
  1155.      }
  1156.      else {           /* Windows version */
  1157. static char far firstready2[]={"First (Left Eye) image is complete"};
  1158.         stopmsg(0,firstready2);
  1159.         clear_screen();
  1160.         }
  1161.       whichimage = 2;
  1162.       plot_setup();
  1163.       plot = standardplot;
  1164.       /* is there a better way to clear the graphics screen ? */
  1165.       if(status = calc())
  1166.      return(status);
  1167.       if(glassestype==3) /* photographer's mode */
  1168.      if(active_system == 0) { /* dos version */
  1169. static char far secondready[]={"Second image (right eye) is ready"};
  1170.         stopmsg(16,secondready);
  1171.      }
  1172.    }
  1173.    return(status);
  1174. }
  1175.  
  1176. /* double version - mainly for testing */
  1177. static int ifs3dfloat()
  1178. {
  1179.    double tmp;
  1180.    double tmpx;
  1181.    double tmpy;
  1182.    double tmpz;
  1183.    VECTOR minvals;
  1184.    VECTOR maxvals;
  1185.    unsigned long maxct,ct;
  1186.    register int col;
  1187.    register int row;
  1188.    register int color;
  1189.  
  1190.    double newx,newy,newz,r,sum;
  1191.  
  1192.    int i,k;
  1193.  
  1194.    /* 3D viewing stuff */
  1195.    MATRIX doublemat;           /* transformation matrix */
  1196.    MATRIX doublemat1;        /* transformation matrix */
  1197.    VECTOR orbitvect;           /* interated function orbit value */
  1198.    VECTOR viewvect;       /* orbit transformed for viewing */
  1199.    VECTOR viewvect1;        /* orbit transformed for viewing */
  1200.    struct affine cvt;
  1201.  
  1202.    /* setup affine screen coord conversion */
  1203.    setup_convert_to_screen(&cvt);
  1204.  
  1205.    srand(1);
  1206.    for(i=0;i<3;i++)
  1207.    {
  1208.       minvals[i] =  100000.0; /* impossible value */
  1209.       maxvals[i] = -100000.0;
  1210.    }
  1211.  
  1212.    setupmatrix(doublemat);
  1213.    if(realtime)
  1214.       setupmatrix(doublemat1);
  1215.  
  1216.    if(diskvideo)        /* this would KILL a disk drive! */
  1217.    {
  1218.       notdiskmsg();
  1219.       return(-1);
  1220.    }
  1221.  
  1222.    orbitvect[0] = 0;
  1223.    orbitvect[1] = 0;
  1224.    orbitvect[2] = 0;
  1225.  
  1226.    maxct = maxit*40L;
  1227.    ct = 0L;
  1228.    while(ct++ < maxct) /* loop until keypress or maxit */
  1229.    {
  1230.       if (ct & 127)          /* reduce the number of keypress checks */
  1231.      if( check_key() )    /* keypress bails out */
  1232.         return(-1);
  1233.       r = rand();     /* generate fudged random number between 0 and 1 */
  1234.       r /= 32767;
  1235.  
  1236.       /* pick which iterated function to execute, weighted by probability */
  1237.       sum = initifs3d[0][12];
  1238.       k = 0;
  1239.       while ( sum < r)
  1240.       {
  1241.      k++;
  1242.      sum += initifs3d[k][12];
  1243.      if (initifs3d[k+1][12] == 0) break;    /* for safety */
  1244.       }
  1245.  
  1246.       /* calculate image of last point under selected iterated function */
  1247.       newx = initifs3d[k][0] * orbitvect[0] +
  1248.       initifs3d[k][1] * orbitvect[1] +
  1249.       initifs3d[k][2] * orbitvect[2] + initifs3d[k][9];
  1250.       newy = initifs3d[k][3] * orbitvect[0] +
  1251.       initifs3d[k][4] * orbitvect[1] +
  1252.       initifs3d[k][5] * orbitvect[2] + initifs3d[k][10];
  1253.       newz = initifs3d[k][6] * orbitvect[0] +
  1254.       initifs3d[k][7] * orbitvect[1] +
  1255.       initifs3d[k][8] * orbitvect[2] + initifs3d[k][11];
  1256.  
  1257.       orbitvect[0] = newx;
  1258.       orbitvect[1] = newy;
  1259.       orbitvect[2] = newz;
  1260.  
  1261.       /* 3D VIEWING TRANSFORM */
  1262.       vmult(orbitvect,doublemat,viewvect);
  1263.       if(realtime)
  1264.      vmult(orbitvect,doublemat1,viewvect1);
  1265.  
  1266.       /* find minz and maxz */
  1267.       if(ct <= waste) /* waste this many points to find minz and maxz */
  1268.       {
  1269.      for(i=0;i<3;i++)
  1270.         if ((tmp = viewvect[i]) < minvals[i])
  1271.            minvals[i] = tmp;
  1272.         else if (tmp > maxvals[i])
  1273.            maxvals[i] = tmp;
  1274.      if(ct == waste)
  1275.      {
  1276.         /* center viewer position on object */
  1277.         view[0] = view[1] = 0; /* center on origin */
  1278.  
  1279.         /* z value of user's eye - should be more negative than extreme
  1280.                negative part of image */
  1281.         view[2] = (minvals[2]-maxvals[2])*(double)ZVIEWER/100.0;
  1282.  
  1283.         /* center image on origin */
  1284.         tmpx = (-minvals[0]-maxvals[0])/(2.0); /* center x */
  1285.         tmpy = (-minvals[1]-maxvals[1])/(2.0); /* center y */
  1286.  
  1287.         /* apply perspective shift */
  1288.         tmpx += ((double)xshift*(xxmax-xxmin))/(xdots)  ;
  1289.         tmpy += ((double)yshift*(yymax-yymin))/(ydots);
  1290.         tmpz = -((double)maxvals[2]);
  1291.         trans(tmpx,tmpy,tmpz,doublemat);
  1292.  
  1293.         if(realtime)
  1294.         {
  1295.            /* center image on origin */
  1296.            tmpx = (-minvals[0]-maxvals[0])/(2.0); /* center x */
  1297.            tmpy = (-minvals[1]-maxvals[1])/(2.0); /* center y */
  1298.  
  1299.            tmpx += ((double)xshift1*(xxmax-xxmin))/(xdots);
  1300.            tmpy += ((double)yshift1*(yymax-yymin))/(ydots);
  1301.            tmpz = -((double)maxvals[2]);
  1302.            trans(tmpx,tmpy,tmpz,doublemat1);
  1303.         }
  1304.      }
  1305.       }
  1306.  
  1307.  
  1308.       if(ct > waste)
  1309.       {
  1310.      /* apply perspective if requested */
  1311.      if(ZVIEWER)
  1312.      {
  1313.         perspective(viewvect);
  1314.         if(realtime)
  1315.            perspective(viewvect1);
  1316.      }
  1317.      if(realtime)
  1318.         whichimage=1;
  1319.      /* plot if inside window */
  1320.      col = cvt.a*viewvect[0] + cvt.b*viewvect[1] + cvt.e + xxadjust;
  1321.      row = cvt.c*viewvect[0] + cvt.d*viewvect[1] + cvt.f + yyadjust;
  1322.      if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  1323.      {
  1324.         color = getcolor(col,row)+1;
  1325.         if( color < colors ) /* color sticks on last value */
  1326.            (*plot)(col,row,color);
  1327.      }
  1328.      if(realtime)
  1329.      {
  1330.         whichimage=2;
  1331.         /* plot if inside window */
  1332.         col = cvt.a*viewvect1[0] + cvt.b*viewvect1[1] + cvt.e + xxadjust1;
  1333.         row = cvt.c*viewvect1[0] + cvt.d*viewvect1[1] + cvt.f + yyadjust1;
  1334.         if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  1335.         {
  1336.            color = getcolor(col,row)+1;
  1337.            if( color < colors ) /* color sticks on last value */
  1338.           (*plot)(col,row,color);
  1339.         }
  1340.      }
  1341.       }
  1342.    } /* end while */
  1343.    return(0);
  1344. }
  1345.  
  1346. int ifs()    /* IFS logic shamelessly converted to integer math */
  1347. {
  1348.    long a,b,c,d,e,f;
  1349.    long  *lifsptr;
  1350.    unsigned long maxct,ct;
  1351.    register int col;
  1352.    register int row;
  1353.    register int color;
  1354.  
  1355.    long localifs[NUMIFS][7];        /* local IFS values */
  1356.    long x,y,newx,newy,r,sum, tempr;
  1357.  
  1358.    int i,j,k;
  1359.    struct affine cvt;
  1360.  
  1361.    /* setup affine screen coord conversion */
  1362.    setup_convert_to_screen(&cvt);
  1363.    a = cvt.a*fudge; b = cvt.b*fudge; c = cvt.c*fudge;
  1364.    d = cvt.d*fudge; e = cvt.e*fudge; f = cvt.f*fudge;
  1365.  
  1366.    srand(1);
  1367.  
  1368.    if(diskvideo) {        /* this would KILL a disk drive! */
  1369.     notdiskmsg();
  1370.     return(-1);
  1371.     }
  1372.  
  1373.    for (i = 0; i < NUMIFS; i++)    /* fill in the local IFS array */
  1374.    for (j = 0; j < IFSPARM; j++)
  1375.      localifs[i][j] = initifs[i][j] * fudge;
  1376.  
  1377.    tempr = fudge / 32767;     /* find the proper rand() fudge */
  1378.  
  1379.    /* make maxct a function of screen size         */
  1380.    /* 1k times maxit at EGA resolution seems about right */
  1381.    maxct = (float)maxit*(1024.0*xdots*ydots)/(640.0*350.0);
  1382.    ct = 0L;
  1383.    x = y = 0;
  1384.    while(ct++ < maxct) /* loop until keypress or maxit */
  1385.    {
  1386.       if (ct & 127)          /* reduce the number of keypress checks */
  1387.      if( check_key() )    /* keypress bails out */
  1388.         return(-1);
  1389.       r = rand();     /* generate fudged random number between 0 and 1 */
  1390.       r *= tempr;
  1391.  
  1392.       /* pick which iterated function to execute, weighted by probability */
  1393.       sum = localifs[0][6];
  1394.       k = 0;
  1395.       while ( sum < r)
  1396.       {
  1397.      k++;
  1398.      sum += localifs[k][6];
  1399.      if (localifs[k+1][6] == 0) break;    /* for safety */
  1400.       }
  1401.  
  1402.       /* calculate image of last point under selected iterated function */
  1403.       newx = multiply(localifs[k][0], x, bitshift) +
  1404.       multiply(localifs[k][1], y, bitshift) +
  1405.       localifs[k][4];
  1406.       newy = multiply(localifs[k][2], x, bitshift) +
  1407.       multiply(localifs[k][3], y, bitshift) +
  1408.       localifs[k][5];
  1409.       x = newx;
  1410.       y = newy;
  1411.  
  1412.       /* plot if inside window */
  1413.       col = (multiply(a,x,bitshift) + multiply(b,y,bitshift) + e) >> bitshift;
  1414.       row = (multiply(c,x,bitshift) + multiply(d,y,bitshift) + f) >> bitshift;
  1415.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  1416.       {
  1417.      /* color is count of hits on this pixel */
  1418.      color = getcolor(col,row)+1;
  1419.      if( color < colors ) /* color sticks on last value */
  1420.         (*plot)(col,row,color);
  1421.       }
  1422.    }
  1423.    return(0);
  1424. }
  1425.  
  1426. static int ifs3dlong()
  1427. {
  1428.    long a,b,c,d,e,f;
  1429.    double tmpx, tmpy, tmpz;
  1430.    extern VECTOR view;
  1431.    long iview[3];      /* perspective viewer's coordinates */
  1432.    long tmp;
  1433.    long maxvals[3];
  1434.    long minvals[3];
  1435.    extern int init3d[];
  1436.    unsigned long maxct,ct;
  1437.    register int col;
  1438.    register int row;
  1439.    register int color;
  1440.  
  1441.    long localifs[NUMIFS][IFS3DPARM];        /* local IFS values */
  1442.    long newx,newy,newz,r,sum, tempr;
  1443.  
  1444.    int i,j,k;
  1445.  
  1446.    /* 3D viewing stuff */
  1447.    MATRIX doublemat;           /* transformation matrix */
  1448.    MATRIX doublemat1;        /* transformation matrix */
  1449.    long longmat[4][4];           /* long version of matrix */
  1450.    long longmat1[4][4];     /* long version of matrix */
  1451.    long orbitvect[3];           /* interated function orbit value */
  1452.    long viewvect[3];        /* orbit transformed for viewing */
  1453.    long viewvect1[3];         /* orbit transformed for viewing */
  1454.    struct affine cvt;
  1455.  
  1456.    srand(1);
  1457.  
  1458.    /* setup affine screen coord conversion */
  1459.    setup_convert_to_screen(&cvt);
  1460.    a = cvt.a*fudge; b = cvt.b*fudge; c = cvt.c*fudge;
  1461.    d = cvt.d*fudge; e = cvt.e*fudge; f = cvt.f*fudge;
  1462.  
  1463.    for(i=0;i<3;i++)
  1464.    {
  1465.       minvals[i] =  1L << 30;
  1466.       maxvals[i] = -minvals[i];
  1467.    }
  1468.  
  1469.    setupmatrix(doublemat);
  1470.    if(realtime)
  1471.       setupmatrix(doublemat1);
  1472.  
  1473.    /* copy xform matrix to long for for fixed point math */
  1474.    for (i = 0; i < 4; i++)
  1475.       for (j = 0; j < 4; j++)
  1476.       {
  1477.      longmat[i][j] = doublemat[i][j] * fudge;
  1478.      if(realtime)
  1479.         longmat1[i][j] = doublemat1[i][j] * fudge;
  1480.       }
  1481.    if(diskvideo)        /* this would KILL a disk drive! */
  1482.    {
  1483.       notdiskmsg();
  1484.       return(-1);
  1485.    }
  1486.  
  1487.    for (i = 0; i < NUMIFS; i++)    /* fill in the local IFS array */
  1488.       for (j = 0; j < IFS3DPARM; j++)
  1489.      localifs[i][j] = initifs3d[i][j] * fudge;
  1490.  
  1491.    tempr = fudge / 32767;     /* find the proper rand() fudge */
  1492.  
  1493.    orbitvect[0] = 0;
  1494.    orbitvect[1] = 0;
  1495.    orbitvect[2] = 0;
  1496.  
  1497.    maxct = maxit*40L;
  1498.    ct = 0L;
  1499.    while(ct++ < maxct) /* loop until keypress or maxit */
  1500.    {
  1501.       if (ct & 127)          /* reduce the number of keypress checks */
  1502.      if( check_key() )    /* keypress bails out */
  1503.         return(-1);
  1504.       r = rand();     /* generate fudged random number between 0 and 1 */
  1505.       r *= tempr;
  1506.  
  1507.       /* pick which iterated function to execute, weighted by probability */
  1508.       sum = localifs[0][12];
  1509.       k = 0;
  1510.       while ( sum < r)
  1511.       {
  1512.      k++;
  1513.      sum += localifs[k][12];
  1514.      if (localifs[k+1][12] == 0) break;    /* for safety */
  1515.       }
  1516.  
  1517.       /* calculate image of last point under selected iterated function */
  1518.       newx = multiply(localifs[k][0], orbitvect[0], bitshift) +
  1519.       multiply(localifs[k][1], orbitvect[1], bitshift) +
  1520.       multiply(localifs[k][2], orbitvect[2], bitshift) + localifs[k][9];
  1521.       newy = multiply(localifs[k][3], orbitvect[0], bitshift) +
  1522.       multiply(localifs[k][4], orbitvect[1], bitshift) +
  1523.       multiply(localifs[k][5], orbitvect[2], bitshift) + localifs[k][10];
  1524.       newz = multiply(localifs[k][6], orbitvect[0], bitshift) +
  1525.       multiply(localifs[k][7], orbitvect[1], bitshift) +
  1526.       multiply(localifs[k][8], orbitvect[2], bitshift) + localifs[k][11];
  1527.  
  1528.       orbitvect[0] = newx;
  1529.       orbitvect[1] = newy;
  1530.       orbitvect[2] = newz;
  1531.  
  1532.       /* 3D VIEWING TRANSFORM */
  1533.       longvmult(orbitvect,longmat,viewvect, bitshift);
  1534.       if(realtime)
  1535.      longvmult(orbitvect,longmat1,viewvect1, bitshift);
  1536.  
  1537.       if(ct <= waste) /* waste this many points to find minz and maxz */
  1538.       {
  1539.      /* find minz and maxz */
  1540.      for(i=0;i<3;i++)
  1541.         if ((tmp = viewvect[i]) < minvals[i])
  1542.            minvals[i] = tmp;
  1543.         else if (tmp > maxvals[i])
  1544.            maxvals[i] = tmp;
  1545.      if(ct == waste)
  1546.      {
  1547.         iview[0] = iview[1] = 0L; /* center viewer on origin */
  1548.  
  1549.         /* z value of user's eye - should be more negative than extreme
  1550.                negative part of image */
  1551.         iview[2] = (long)((minvals[2]-maxvals[2])*(double)ZVIEWER/100.0);
  1552.  
  1553.         /* center image on origin */
  1554.         tmpx = (-minvals[0]-maxvals[0])/(2.0*fudge); /* center x */
  1555.         tmpy = (-minvals[1]-maxvals[1])/(2.0*fudge); /* center y */
  1556.  
  1557.         /* apply perspective shift */
  1558.         tmpx += ((double)xshift*(xxmax-xxmin))/(xdots)  ;
  1559.         tmpy += ((double)yshift*(yymax-yymin))/(ydots);
  1560.         tmpz = -((double)maxvals[2]);
  1561.         tmpz /= fudge;
  1562.         trans(tmpx,tmpy,tmpz,doublemat);
  1563.  
  1564.         if(realtime)
  1565.         {
  1566.            /* center image on origin */
  1567.            tmpx = (-minvals[0]-maxvals[0])/(2.0*fudge); /* center x */
  1568.            tmpy = (-minvals[1]-maxvals[1])/(2.0*fudge); /* center y */
  1569.  
  1570.            tmpx += ((double)xshift1*(xxmax-xxmin))/(xdots);
  1571.            tmpy += ((double)yshift1*(yymax-yymin))/(ydots);
  1572.            tmpz = -((double)maxvals[2]);
  1573.            tmpz /= fudge;
  1574.            trans(tmpx,tmpy,tmpz,doublemat1);
  1575.         }
  1576.  
  1577.         for(i=0;i<3;i++)
  1578.         {
  1579.            view[i] = iview[i];
  1580.            view[i] /= fudge;
  1581.         }
  1582.  
  1583.         /* copy xform matrix to long for for fixed point math */
  1584.         for (i = 0; i < 4; i++)
  1585.            for (j = 0; j < 4; j++)
  1586.            {
  1587.           longmat[i][j] = doublemat[i][j] * fudge;
  1588.           if(realtime)
  1589.              longmat1[i][j] = doublemat1[i][j] * fudge;
  1590.            }
  1591.      }
  1592.       }
  1593.       if(ct > waste)
  1594.       {
  1595.      /* apply perspective if requested */
  1596.      if(ZVIEWER && ct > waste)
  1597.      {
  1598.         if(debugflag==22 || ZVIEWER < 100) /* use float for small persp */
  1599.         {
  1600.            /* use float perspective calc */
  1601.            VECTOR tmpv;
  1602.            for(i=0;i<3;i++)
  1603.            {
  1604.           tmpv[i] = viewvect[i];
  1605.           tmpv[i] /= fudge;
  1606.            }
  1607.            perspective(tmpv);
  1608.            for(i=0;i<3;i++)
  1609.           viewvect[i] = tmpv[i]*fudge;
  1610.            if(realtime)
  1611.            {
  1612.           for(i=0;i<3;i++)
  1613.           {
  1614.              tmpv[i] = viewvect1[i];
  1615.              tmpv[i] /= fudge;
  1616.           }
  1617.           perspective(tmpv);
  1618.           for(i=0;i<3;i++)
  1619.              viewvect1[i] = tmpv[i]*fudge;
  1620.            }
  1621.         }
  1622.         else
  1623.         {
  1624.            longpersp(viewvect,iview,bitshift);
  1625.            if(realtime)
  1626.           longpersp(viewvect1,iview,bitshift);
  1627.         }
  1628.      }
  1629.      if(realtime)
  1630.      whichimage=1;
  1631.      /* plot if inside window */
  1632.      col = (multiply(a,viewvect[0],bitshift)+
  1633.         multiply(b,viewvect[1],bitshift)+e) >> bitshift;
  1634.      row = (multiply(c,viewvect[0],bitshift)+
  1635.         multiply(d,viewvect[1],bitshift)+f) >> bitshift;
  1636.      col += xxadjust;
  1637.      row += yyadjust;
  1638.  
  1639.      if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  1640.      {
  1641.         color = getcolor(col,row)+1;
  1642.         if( color < colors ) /* color sticks on last value */
  1643.            (*plot)(col,row,color);
  1644.      }
  1645.      if(realtime)
  1646.      {
  1647.         whichimage=2;
  1648.         /* plot if inside window */
  1649.         col = (multiply(a,viewvect1[0],bitshift)+
  1650.            multiply(b,viewvect1[1],bitshift)+e) >> bitshift;
  1651.         row = (multiply(c,viewvect1[0],bitshift)+
  1652.            multiply(d,viewvect1[1],bitshift)+f) >> bitshift;
  1653.         col += xxadjust1;
  1654.         row += yyadjust1;
  1655.         if ( 0 <= col && col < xdots && 0 <= row && row < ydots)
  1656.         {
  1657.            color = getcolor(col,row)+1;
  1658.            if( color < colors ) /* color sticks on last value */
  1659.           (*plot)(col,row,color);
  1660.         }
  1661.      }
  1662.       }
  1663.    }
  1664.    return(0);
  1665. }
  1666.  
  1667. static void setupmatrix(MATRIX doublemat)
  1668. {
  1669.    /* build transformation matrix */
  1670.    identity (doublemat);
  1671.  
  1672.    /* apply rotations - uses the same rotation variables as line3d.c */
  1673.    xrot ((double)XROT / 57.29577,doublemat);
  1674.    yrot ((double)YROT / 57.29577,doublemat);
  1675.    zrot ((double)ZROT / 57.29577,doublemat);
  1676.  
  1677.    /* apply scale */
  1678. /*   scale((double)XSCALE/100.0,(double)YSCALE/100.0,(double)ROUGH/100.0,doublemat);*/
  1679.  
  1680. }
  1681.  
  1682. int orbit3dfloat()
  1683. {
  1684.    display3d = -1;
  1685.    if(0 < glassestype && glassestype < 3)
  1686.       realtime = 1;
  1687.    else
  1688.       realtime = 0;
  1689.    return(funny_glasses_call(orbit3dfloatcalc));
  1690. }
  1691. int orbit3dlong()
  1692. {
  1693.    display3d = -1;
  1694.    if(0 < glassestype && glassestype < 3)
  1695.       realtime = 1;
  1696.    else
  1697.       realtime = 0;
  1698.    return(funny_glasses_call(orbit3dlongcalc));
  1699. }
  1700.  
  1701. int ifs3d()
  1702. {
  1703.    display3d = -1;
  1704.  
  1705.    if(0 < glassestype && glassestype < 3)
  1706.       realtime = 1;
  1707.    else
  1708.       realtime = 0;
  1709.    if(floatflag)
  1710.       return(funny_glasses_call(ifs3dfloat)); /* double version of ifs3d */
  1711.    else
  1712.       return(funny_glasses_call(ifs3dlong));  /* long version of ifs3d     */
  1713. }
  1714.  
  1715.