home *** CD-ROM | disk | FTP | other *** search
/ Fractal Creations (Second Edition) / FRACTALS_2E.iso / frasrc.exe / LINE3D.C < prev    next >
C/C++ Source or Header  |  1993-08-21  |  80KB  |  2,749 lines

  1. /******************************************************************************/
  2. /* This file contains a 3D replacement for the out_line function called            */
  3. /* by the decoder. The purpose is to apply various 3D transformations            */
  4. /* before displaying points. Called once per line of the input file.                */
  5. /*                                                                                                        */
  6. /* This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.            */
  7. /*                                                                                                        */
  8. /* Original Author Tim Wegner, with extensive help from Marc Reinig.                */
  9. /*****************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <limits.h>
  14. #ifndef XFRACT
  15. #include <dos.h>
  16. #endif
  17. #include "fractint.h"
  18. #include "prototyp.h"
  19.  
  20. struct point
  21. {
  22.     int x;
  23.     int y;
  24.     int color;
  25. };
  26.  
  27. /* routines in this module    */
  28.  
  29. static void _fastcall vdraw_line(double *,double *,int);
  30. static void (_fastcall *fillplot)(int,int,int);
  31. static void (_fastcall *normalplot)(int,int,int);
  32. static void _fastcall putminmax(int x,int y,int color);
  33. static void _fastcall clipcolor(int x,int y,int color);
  34. static void _fastcall T_clipcolor(int x,int y,int color);
  35. static void _fastcall interpcolor(int x,int y,int color);
  36. static void corners(),draw_light_box();
  37. static void _fastcall putatriangle(struct point pt1,struct point pt2,
  38.                     struct point pt3,int color);
  39. static int _fastcall offscreen(struct point pt);
  40. static int  H_R(),R_H();
  41. static int  startdisk1(char *File_Name2, FILE *Source, int overlay);
  42. static int  set_pixel_buff();
  43. static void line3d_cleanup();
  44. extern int glassestype, whichimage;
  45. void (_fastcall *standardplot)(int,int,int);
  46.  
  47. static    int line_length1;
  48. static    int T_header_24 = 18; /* Size of current Targa-24 header */
  49. extern    BYTE dacbox[256][3];
  50. MATRIX m;                /* transformation matrix */
  51. void (*mult_vec)(VECTOR) = mult_vec_c;
  52. extern int iit;                 /* iit flag */
  53. static    FILE *File_Ptr1 = NULL;
  54. int Ambient;
  55. static unsigned int IAmbient;
  56. int RANDOMIZE;
  57. static int rand_factor;
  58. int haze;
  59. static int HAZE_MULT;
  60. int Real_V = 0; /* mrr Actual value of V for fillytpe>4 monochrome images */
  61.  
  62. char light_name[80] = "fract001";
  63. int Targa_Overlay, error;
  64. extern int Targa_Out;
  65. char targa_temp[14] = "fractemp.tga";
  66. static void File_Error (char *File_Name1, int ERROR);
  67. static BYTE T24=24;
  68. static BYTE T32=32;
  69. static BYTE upr_lwr[4];
  70. static int T_Safe; /* Original Targa Image successfully copied to targa_temp */
  71. int P = 250; /* Perspective dist used when viewing light vector */
  72. static void draw_rect (VECTOR V0, VECTOR V1, VECTOR V2, VECTOR V3, int color,
  73.                             int rect);
  74. static VECTOR light_direction;
  75.  
  76. BYTE back_color[3];
  77. static BYTE Real_Color; /* Actual color of cur pixel */
  78. extern int dotmode; /* video access method, 11 if really disk video */
  79. extern int calc_status;
  80. extern long calctime;
  81. extern int got_status,currow;
  82.  
  83.  
  84. static int RO, CO, CO_MAX; /*  For use in Acrospin support */
  85. static char far acro_s1[] =
  86.     {"Set Layer 1\nSet Color 2\nEndpointList X Y Z Name\n"};
  87. static char far acro_s2[] = {"LineList From To\n"};
  88. static char far s3[] = {"{ Created by FRACTINT Ver. "};
  89. static char far s3a[] = {" }\n\n"};
  90. #ifndef XFRACT
  91. static char banner[] ="%Fs%#4.2f%Fs";
  92. #else
  93. static char banner[] ="%s%#4.2f%s";
  94. #endif
  95. char ray_name[80] = "fract001";
  96.  
  97. char preview = 0;
  98. char showbox = 0;
  99. static int localpreviewfactor;
  100. int previewfactor = 20;
  101. int xadjust = 0;
  102. int yadjust = 0;
  103. int xxadjust;
  104. int yyadjust;
  105. int xshift;
  106. int yshift;
  107. extern int overflow;
  108. extern int filetype;
  109. extern char usr_floatflag;
  110. extern int xdots, ydots, colors, sxoffs, syoffs;
  111. extern int debugflag;
  112. extern SEGTYPE extraseg;
  113. extern unsigned height;
  114. extern int rowcount;        /* in general.asm */
  115. extern int init3d[];        /* 3D arguments (FRACTINT.C) */
  116. extern long far *lx0;
  117. extern int transparent[2];    /* transparency min/max */
  118. extern int pot16bit;
  119. extern int filecolors;
  120. extern void (*outln_cleanup)();
  121.  
  122. static int zcoord = 256;
  123. static double aspect;            /* aspect ratio */
  124. static int evenoddrow;
  125.  
  126. static float far *sinthetaarray;    /* all sine        thetas go here  */
  127. static float far *costhetaarray;    /* all cosine thetas go here */
  128.  
  129. static double rXrscale;         /* precalculation factor */
  130.  
  131. static int persp;    /* flag for indicating perspective transformations */
  132. int bad_value = -10000; /* set bad values to this */
  133. int bad_check = -3000;    /* check values against this to determine if good */
  134.  
  135. /* this array remembers the previous line */
  136. struct point far *lastrow;
  137.  
  138. static struct point p1,p2,p3;
  139.  
  140. struct f_point
  141. {
  142.     float x;
  143.     float y;
  144.     float color;
  145. }
  146. far *f_lastrow;
  147.  
  148.  
  149. int RAY = 0; /* Flag to generate Ray trace compatible files in 3d */
  150. int BRIEF = 0; /* 1 = short ray trace files */
  151. extern int release; /* Current release level of Fractint */
  152. static int _fastcall RAY_Header(void);
  153. static void _fastcall triangle_bounds(float pt_t[3][3]);
  154. static int _fastcall out_triangle(struct f_point pt1, struct f_point pt2,
  155.             struct f_point pt3, int c1, int c2, int c3);
  156. static float min_xyz[3], max_xyz[3]; /* For Raytrace output */
  157. static int _fastcall start_object(void);
  158. static int _fastcall end_object(int triout);
  159. extern unsigned numcolors; /* number of colors in original GIF */
  160. static long num_tris; /* number of triangles output to ray trace file */
  161.  
  162. /* array of min and max x values used in triangle fill */
  163. struct minmax
  164. {
  165.     int minx;
  166.     int maxx;
  167. }
  168. far *minmax_x;
  169.  
  170. VECTOR view;    /* position of observer for perspective */
  171. VECTOR cross;
  172. VECTOR tmpcross;
  173.  
  174. struct point oldlast =
  175. {
  176.     0, 0, 0
  177. };    /* old pixels */
  178.  
  179. void line3d_overlay() {
  180. }    /* for restore_active_ovly */
  181.  
  182. int line3d(BYTE *pixels, unsigned linelen)
  183. {
  184.     int tout; /*  triangle has been sent to ray trace file */
  185.     int RND;
  186.     float f_water; /* transformed WATERLINE for ray trace files */
  187.  
  188.     /* these values come from FRACTINT.C */
  189.  
  190.     /* These variables must preserve their values across calls */
  191.     static float    deltaphi;  /* increment of latitude, longitude */
  192.     static double rscale;            /* surface roughness factor */
  193.     static long xcenter,ycenter;            /* circle center */
  194.     double r0;
  195.     int xcenter0,ycenter0; /* Unfudged versions */
  196.  
  197.     static double sclx,scly,sclz;        /* scale factors */
  198.     static double R;                /* radius values */
  199.     static double Rfactor;            /* for intermediate calculation */
  200.     MATRIX lightm;                /* m w/no trans, keeps obj. on screen */
  201.     static LMATRIX lm;                /* "" */
  202.     static LVECTOR lview;            /* for perspective views */
  203.     static double zcutoff;            /* perspective backside cutoff value */
  204.     static float twocosdeltaphi;
  205.     static float cosphi,sinphi;            /* precalculated sin/cos of longitude */
  206.     static float oldcosphi1,oldsinphi1;
  207.     static float oldcosphi2,oldsinphi2;
  208.     double r;                    /* sphere radius */
  209.     double xval,yval,zval;            /* rotation values */
  210.     float costheta,sintheta;            /* precalculated sin/cos of latitude */
  211.     float twocosdeltatheta;
  212.  
  213.     int next; /* used by preview and grid */
  214.     int col;                    /* current column (original GIF) */
  215.     struct point cur;                /* current pixels */
  216.     struct point old;                /* old pixels */
  217.  
  218.     static struct point bad;            /* out of range value */
  219.  
  220.     struct f_point f_cur;
  221.     struct f_point f_old;
  222.     static struct f_point f_bad;            /* out of range value */
  223.  
  224.     static BYTE far *fraction;/* float version of pixels array */
  225.  
  226.     VECTOR v;                    /* double vector */
  227.     VECTOR v1,v2;
  228.     VECTOR crossavg;
  229.     char crossnotinit;                /* flag for crossavg init indication */
  230.  
  231.     double v_length;
  232.     VECTOR origin, direct, tmp;
  233.     LVECTOR lv;                    /* long equivalent of v */
  234.     LVECTOR lv0;                 /* long equivalent of v */
  235.  
  236.     /* corners of transformed xdotx by ydots x colors box */
  237.     double xmin, ymin, zmin, xmax, ymax, zmax;
  238.     int i,j;
  239.     int lastdot;
  240.  
  241.     long fudge;
  242.  
  243.     ENTER_OVLY(OVLY_LINE3D);
  244.  
  245.     fudge = 1L<<16;
  246.  
  247.  
  248.     if(transparent[0] || transparent[1])
  249.         plot = normalplot = T_clipcolor;    /*  Use transparent plot function */
  250.     else            /* Use the usual FRACTINT plot function with clipping */
  251.         plot = normalplot = clipcolor;
  252.  
  253.     currow = rowcount; /* use separate variable to allow for pot16bit files */
  254.     if (pot16bit)
  255.         currow >>= 1;
  256.  
  257.     /************************************************************************/
  258.     /* This IF clause is executed ONCE per image. All precalculations are    */
  259.     /* done here, with out any special concern about speed. DANGER -            */
  260.     /* communication with the rest of the program is generally via static    */
  261.     /* or global variables.                                                                    */
  262.     /************************************************************************/
  263.     if(rowcount++ == 0)
  264.     {
  265.         long check_extra;
  266.         float theta,theta1,theta2;    /* current,start,stop latitude */
  267.         float phi1,phi2;            /* current start,stop longitude */
  268.         float    deltatheta;        /* increment of latitude */
  269.         outln_cleanup = line3d_cleanup;
  270.  
  271.         calctime = evenoddrow = 0;
  272.         /* mark as in-progress, and enable <tab> timer display */
  273.         calc_status = 1;
  274.  
  275.         IAmbient = (unsigned int) (255 * (float)(100 - Ambient) / 100.0);
  276.         if (IAmbient < 1)        IAmbient = 1;
  277.  
  278.         tout = 0;
  279.         num_tris = 0;
  280.  
  281.         /* Open file for RAY trace output and write header */
  282.         if (RAY)
  283.         {
  284.             RAY_Header();
  285.             xxadjust = yyadjust = 0; /* Disable shifting in ray tracing */
  286.             xshift = yshift = 0;
  287.         }
  288.  
  289.         CO_MAX=CO=RO=0;
  290.  
  291.         upr_lwr[0] = xdots & 0xff;
  292.         upr_lwr[1] = xdots >> 8;
  293.         upr_lwr[2] = ydots &  0xff;
  294.         upr_lwr[3] = ydots >> 8;
  295.         line_length1 = 3 * xdots;        /*  line length @ 3 bytes per pixel  */
  296.         error = 0;
  297.  
  298.         if (whichimage < 2)
  299.             T_Safe = 0; /* Not safe yet to mess with the source image */
  300.  
  301.         if (Targa_Out && !((glassestype==1 || glassestype==2) && whichimage==2))
  302.         {
  303.             if (Targa_Overlay)    
  304.             {        
  305.                 /* Make sure target file is a supportable Targa File */    
  306.                 if(targa_validate (light_name))        
  307.                     return(-1);
  308.             }        
  309.             else
  310.             {
  311.                 check_writefile(light_name,".tga");
  312.                 if (startdisk1(light_name, NULL, 0))    /* Open new file */
  313.                     return(-1);
  314.             }
  315.         }
  316.  
  317.         rand_factor = 14 - RANDOMIZE;
  318.  
  319.         zcoord = filecolors;
  320.  
  321.         crossavg[0] = 0;
  322.         crossavg[1] = 0;
  323.         crossavg[2] = 0;
  324.  
  325.         /*********************************************************************/
  326.         /*  Memory allocation - assumptions - a 64K segment starting at        */
  327.         /*  extraseg has been grabbed. It may have other purposes elsewhere, */
  328.         /*  but it is assumed that it is totally free for use here. Our        */
  329.         /*  strategy is to assign all the far pointers needed here to various*/
  330.         /*  spots in the extra segment, depending on the pixel dimensions of */
  331.         /*  the video mode, and check whether we have run out. There is        */
  332.         /*  basically one case where the extra segment is not big enough        */
  333.         /*  -- SPHERE mode with a fill type that uses putatriangle() (array    */
  334.         /*  minmax_x) at the largest legal resolution of MAXPIXELSxMAXPIXELS or            */
  335.         /*  thereabouts. In that case we use farmemalloc to grab    memory        */
  336.         /*  for minmax_x. This memory is never freed.                                */
  337.         /*********************************************************************/
  338.  
  339.         /* lastrow stores the previous row of the original GIF image for
  340.             the purpose of filling in gaps with triangle procedure */
  341.         lastrow = MK_FP(extraseg,0);
  342.  
  343.         check_extra = sizeof(*lastrow)*xdots;
  344.         if(SPHERE)
  345.         {
  346.             sinthetaarray = (float far *)(lastrow+xdots);
  347.             check_extra += sizeof(*sinthetaarray)*xdots;
  348.  
  349.             costhetaarray = (float far *)(sinthetaarray+xdots);
  350.             check_extra += sizeof(*costhetaarray)*xdots;
  351.  
  352.             f_lastrow = (struct f_point far *)(costhetaarray+xdots);
  353.         }
  354.         else
  355.             f_lastrow = (struct f_point far *)(lastrow+xdots);
  356.         check_extra += sizeof(*f_lastrow)*(xdots);
  357.  
  358.         if(pot16bit)
  359.         {
  360.             fraction = (BYTE far *)(f_lastrow+xdots);
  361.             check_extra += sizeof(*fraction)*xdots;
  362.         }
  363.         minmax_x = (struct minmax *)NULL;
  364.  
  365.         /* these fill types call putatriangle which uses minmax_x */
  366.         if( FILLTYPE == 2 || FILLTYPE == 3 || FILLTYPE == 5 || FILLTYPE == 6)
  367.         {
  368.             /* end of arrays if we use extra segement */
  369.             check_extra += sizeof(struct minmax)*ydots;
  370.             if(check_extra > (1L<<16)) /* run out of extra segment? */
  371.             {
  372.                 static struct minmax far *got_mem = NULL;
  373.                 /* not using extra segment so decrement check_extra */
  374.                 check_extra -= sizeof(struct minmax)*ydots;
  375.                 if(got_mem == NULL)
  376.                     got_mem = (struct minmax far *)(farmemalloc(MAXPIXELS *
  377.                 sizeof(struct minmax)));
  378.  
  379.                 if(got_mem)
  380.                     minmax_x = got_mem;
  381.                 else
  382.                 {
  383.                     EXIT_OVLY;
  384.                     return(-1);
  385.                 }
  386.             }
  387.             else /* ok to use extra segment */
  388.             {
  389.                 if(pot16bit)
  390.                     minmax_x = (struct minmax far *)(fraction+xdots);
  391.                 else
  392.                     minmax_x = (struct minmax far *)(f_lastrow+xdots);
  393.  
  394.             }
  395.         }
  396.  
  397.         if(debugflag == 2222 || check_extra > (1L<<16))
  398.         {
  399.             char tmpmsg[70];
  400.             static char far extramsg[] = {" of extra segment"};
  401. #ifndef XFRACT
  402.             sprintf(tmpmsg,"used %ld%Fs", check_extra, extramsg);
  403. #else
  404.             sprintf(tmpmsg,"used %ld%s", check_extra, extramsg);
  405. #endif
  406.             stopmsg(4,tmpmsg);
  407.         }
  408.  
  409.         /* get scale factors */
  410.         sclx =    XSCALE/100.0;
  411.         scly =    YSCALE/100.0;
  412.         if (ROUGH)
  413.             sclz = -ROUGH/100.0;
  414.         else
  415.             rscale = sclz = -0.0001; /* if rough=0 make it very flat but plot something */
  416.  
  417.         /* aspect ratio calculation - assume screen is 4 x 3 */
  418.         aspect = (double)xdots*.75/(double)ydots;
  419.  
  420.         if(SPHERE==FALSE)  /* skip this slow stuff in sphere case */
  421.         {
  422.         /*********************************************************************/
  423.         /* What is done here is to create a single matrix, m, which has        */
  424.         /* scale, rotation, and shift all combined. This allows us to use        */
  425.         /* a single matrix to transform any point. Additionally, we create      */
  426.         /* two perspective vectors.                                                        */
  427.         /*                                                                                            */
  428.         /* Start with a unit matrix. Add scale and rotation. Then calculate     */
  429.         /* the perspective vectors. Finally add enough translation to center    */
  430.         /* the final image plus whatever shift the user has set.                    */
  431.         /*********************************************************************/
  432.  
  433.             /* start with identity */
  434.             identity (m);
  435.             identity (lightm);
  436.  
  437.             /* translate so origin is in center of box, so that when we rotate */
  438.             /* it, we do so through the center */
  439.             trans ( (double)xdots/(-2.0),(double)ydots/(-2.0),
  440.                     (double)zcoord/(-2.0),m);
  441.             trans ( (double)xdots/(-2.0),(double)ydots/(-2.0),
  442.                     (double)zcoord/(-2.0),lightm);
  443.  
  444.             /* apply scale factors */
  445.             scale(sclx,scly,sclz,m);
  446.             scale(sclx,scly,sclz,lightm);
  447.  
  448.             /* rotation values - converting from degrees to radians */
  449.             xval = XROT / 57.29577;
  450.             yval = YROT / 57.29577;
  451.             zval = ZROT / 57.29577;
  452.  
  453.             if (RAY)    {xval = yval = zval = 0;}
  454.  
  455.             xrot (xval,m);
  456.             xrot (xval,lightm);
  457.             yrot (yval,m);
  458.             yrot (yval,lightm);
  459.             zrot (zval,m);
  460.             zrot (zval,lightm);
  461.  
  462.             /* Find values of translation that make all x,y,z negative */
  463.             /* m current matrix */
  464.             /* 0 means don't show box */
  465.             /* returns minimum and maximum values of x,y,z in fractal */
  466.             corners(m,0,&xmin,&ymin,&zmin,&xmax,&ymax,&zmax);
  467.         }
  468.  
  469.         /* perspective 3D vector - lview[2] == 0 means no perspective */
  470.  
  471.         /* set perspective flag */
  472.         persp = 0;
  473.         if (ZVIEWER != 0)
  474.         {
  475.             persp = 1;
  476.             if(ZVIEWER < 80) /* force float */
  477.                 usr_floatflag |= 2; /* turn on second bit */
  478.         }
  479.  
  480.         /* set up view vector, and put viewer in center of screen */
  481.         lview[0] = xdots >> 1;
  482.         lview[1] = ydots >> 1;
  483.  
  484.         /* z value of user's eye - should be more negative than extreme
  485.                                 negative part of image */
  486.         if(SPHERE) /* sphere case */
  487.             lview[2] = -(long)((double)ydots*(double)ZVIEWER/100.0);
  488.         else    /* non-sphere case */
  489.             lview[2] = (long)((zmin-zmax)*(double)ZVIEWER/100.0);
  490.  
  491.         view[0] = lview[0];
  492.         view[1] = lview[1];
  493.         view[2] = lview[2];
  494.         lview[0] = lview[0] << 16;
  495.         lview[1] = lview[1] << 16;
  496.         lview[2] = lview[2] << 16;
  497.  
  498.         if(SPHERE==FALSE) /* sphere skips this */
  499.         {
  500.             /* translate back exactly amount we translated earlier plus enough
  501.                 to center image so maximum values are non-positive */
  502.             trans(((double)xdots-xmax-xmin)/2,((double)ydots-ymax-ymin) / 2,
  503.                 -zmax,m);
  504.  
  505.             /* Keep the box centered and on screen regardless of shifts */
  506.             trans(((double)xdots-xmax-xmin)/2,((double)ydots-ymax-ymin)/2,
  507.                 -zmax,lightm);
  508.  
  509.             trans((double)(xshift),(double)(-yshift),0.0,m);
  510.  
  511.             /* matrix m now contains ALL those transforms composed together !!
  512.                 convert m to long integers shifted 16 bits */
  513.             for (i = 0; i < 4; i++)
  514.                 for (j = 0; j < 4; j++)
  515.                     lm[i][j] = m[i][j] * 65536.0;
  516.  
  517.         }
  518.         else /* sphere stuff goes here */
  519.         {
  520.             /* Sphere is on side - north pole on right. Top is -90 degrees
  521.                 latitude; bottom 90 degrees */
  522.  
  523.             /* Map X to this LATITUDE range */
  524.             theta1 = THETA1*PI/180.0;
  525.             theta2 = THETA2*PI/180.0;
  526.  
  527.             /* Map Y to this LONGITUDE range */
  528.             phi1    = PHI1*PI/180.0;
  529.             phi2    = PHI2*PI/180.0;
  530.  
  531.             theta = theta1;
  532.  
  533.         /*********************************************************************/
  534.         /* Thanks to Hugh Bray for the following idea: when calculating        */
  535.         /* a table of evenly spaced sines or cosines, only a few initial        */
  536.         /* values need be calculated, and the remaining values can be            */
  537.         /* gotten from a derivative of the sine/cosine angle sum formula        */
  538.         /* at the cost of one multiplication and one addition per value!        */
  539.         /*                                                                                            */
  540.         /* This idea is applied once here to get a complete table for            */
  541.         /* latitude, and near the bottom of this routine to incrementally        */
  542.         /* calculate longitude.                                                                */
  543.         /*                                                                                            */
  544.         /* Precalculate 2*cos(deltaangle), sin(start) and sin(start+delta).    */
  545.         /* Then apply recursively:                                                            */
  546.         /*    sin(angle+2*delta) = sin(angle+delta) * 2cosdelta - sin(angle)        */
  547.         /*                                                                                            */
  548.         /* Similarly for cosine. Neat!                                                     */
  549.         /*********************************************************************/
  550.  
  551.             deltatheta = (float)(theta2 - theta1)/(float)linelen;
  552.  
  553.             /* initial sin,cos theta */
  554.             sinthetaarray[0] = sin((double)theta);
  555.             costhetaarray[0] = cos((double)theta);
  556.             sinthetaarray[1] = sin((double)(theta + deltatheta));
  557.             costhetaarray[1] = cos((double)(theta + deltatheta));
  558.  
  559.             /* sin,cos delta theta */
  560.             twocosdeltatheta = 2.0*cos((double)deltatheta);
  561.  
  562.             /* build table of other sin,cos with trig identity */
  563.             for(i=2;i<linelen;i++)
  564.             {
  565.                 sinthetaarray[i] = sinthetaarray[i-1]*twocosdeltatheta-
  566.                     sinthetaarray[i-2];
  567.                 costhetaarray[i] = costhetaarray[i-1]*twocosdeltatheta-
  568.                     costhetaarray[i-2];
  569.             }
  570.  
  571.             /* now phi - these calculated as we go - get started here */
  572.             deltaphi    = (float)(phi2    - phi1  )/(float)height;
  573.  
  574.             /* initial sin,cos phi */
  575.  
  576.             sinphi = oldsinphi1 = sin((double)phi1);
  577.             cosphi = oldcosphi1 = cos((double)phi1);
  578.             oldsinphi2 = sin((double)(phi1+deltaphi));
  579.             oldcosphi2 = cos((double)(phi1+deltaphi));
  580.  
  581.             /* sin,cos delta phi */
  582.             twocosdeltaphi = 2*cos((double)deltaphi);
  583.  
  584.             xcenter0 = xcenter = xdots/2 + xshift;
  585.             ycenter0 = ycenter = ydots/2 - yshift;
  586.  
  587.             /* affects how rough planet terrain is */
  588.             if (ROUGH)
  589.                 rscale = .3*ROUGH/100.0;
  590.  
  591.             /* radius of planet */
  592.             R = (double)(ydots)/2;
  593.  
  594.             /* precalculate factor */
  595.             rXrscale = R*rscale;
  596.  
  597.             sclz = sclx = scly = RADIUS/100.0; /* Need x,y,z for RAY */
  598.  
  599.             /* adjust x scale factor for aspect */
  600.             sclx *= aspect;
  601.  
  602.             /* precalculation factor used in sphere calc */
  603.             Rfactor = rscale*R/(double)zcoord;
  604.  
  605.             if(persp) /* precalculate fudge factor */
  606.             {
  607.                 double radius;
  608.                 double zview;
  609.                 double angle;
  610.  
  611.                 xcenter  = xcenter << 16;
  612.                 ycenter  = ycenter << 16;
  613.  
  614.                 Rfactor *= 65536.0;
  615.                 R            *= 65536.0;
  616.  
  617.                 /* calculate z cutoff factor
  618.                     attempt to prevent out-of-view surfaces from being written */
  619.                 zview = -(long)((double)ydots*(double)ZVIEWER/100.0);
  620.                 radius = (double)(ydots)/2;
  621.                 angle = atan(-radius/(zview+radius));
  622.                 zcutoff = -radius - sin(angle)*radius;
  623.                 zcutoff *= 1.1; /* for safety */
  624.                 zcutoff *= 65536;
  625.             }
  626.         }
  627.  
  628.         /* set fill plot function */
  629.         if(FILLTYPE != 3)
  630.             fillplot = interpcolor;
  631.         else
  632.         {
  633.             fillplot = clipcolor;
  634.  
  635.             if(transparent[0] || transparent[1])
  636.                 /*    If transparent colors are set */
  637.                 fillplot = T_clipcolor;  /*  Use the transparent plot function  */
  638.         }
  639.  
  640.         /* Both Sphere and Normal 3D */
  641.         direct[0] = light_direction[0] = XLIGHT;
  642.         direct[1] = light_direction[1] = -YLIGHT;
  643.         direct[2] = light_direction[2] = ZLIGHT;
  644.  
  645.         /* Needed because sclz = -ROUGH/100 and light_direction is transformed
  646.             in FILLTYPE 6 but not in 5. */
  647.         if (FILLTYPE == 5)
  648.             direct[2] = light_direction[2] = -ZLIGHT;
  649.  
  650.         if(FILLTYPE==6) /* transform light direction */
  651.         {
  652.             /* Think of light direction  as a vector with tail at (0,0,0) and
  653.                 head at (light_direction). We apply the transformation to
  654.                 BOTH head and tail and take the difference */
  655.  
  656.             v[0] = 0.0;
  657.             v[1] = 0.0;
  658.             v[2] = 0.0;
  659.             vmult(v,m,v);
  660.             vmult(light_direction,m,light_direction);
  661.  
  662.             for (i=0;i<3;i++)        light_direction[i] -= v[i];
  663.         }
  664.         normalize_vector(light_direction);
  665.  
  666.         if(preview && showbox)
  667.         {
  668.             normalize_vector(direct);
  669.  
  670.             /* move light vector to be more clear with grey scale maps */
  671.             origin[0] = (3 * xdots) / 16;
  672.             origin[1] = (3 * ydots) / 4;
  673.             if (FILLTYPE == 6)
  674.                 origin[1] = (11 * ydots) / 16;
  675.  
  676.             origin[2] = 0.0;
  677.  
  678.             v_length = min (xdots, ydots) / 2;
  679.             if (persp && ZVIEWER <= P)
  680.                 v_length *= (long)(P + 600) /((long)(ZVIEWER+600) * 2);
  681.  
  682.             /* Set direct[] to point from origin[] in direction of
  683.                 untransformed light_direction (direct[]). */
  684.             for (i=0;i<3;i++)
  685.                 direct[i] = origin[i] + direct[i] * v_length;
  686.  
  687.             /* center light box */
  688.             for (i=0;i<2;i++)
  689.             {
  690.                 tmp[i] = (direct[i] - origin[i]) / 2;
  691.                 origin[i] -= tmp[i];
  692.                 direct[i] -= tmp[i];
  693.             }
  694.  
  695.             /* Draw light source vector and box containing it, draw_light_box
  696.                 will transform them if necessary. */
  697.             draw_light_box (origin,direct,lightm);
  698.             /* draw box around original field of view to help visualize effect
  699.                 of rotations 1 means show box - xmin etc. do nothing here */
  700.             if (!SPHERE)
  701.                 corners(m,1,&xmin,&ymin,&zmin,&xmax,&ymax,&zmax);
  702.         }
  703.  
  704.         /* bad has values caught by clipping */
  705.         f_bad.x            = bad.x            = bad_value;
  706.         f_bad.y            = bad.y            = bad_value;
  707.         f_bad.color = bad.color = bad_value;
  708.         for(i=0;i<linelen;i++)
  709.         {
  710.             lastrow[i]    = bad;
  711.             f_lastrow[i] = f_bad;
  712.         }
  713.         got_status = 3;
  714.         if(iit>0)
  715.         {
  716.             load_mat(m); /* load matrix into iit registers */
  717.             mult_vec = mult_vec_iit;
  718.         }
  719.         else
  720.             mult_vec = mult_vec_c;
  721.     } /* end of once-per-image intializations */
  722.  
  723.     crossnotinit = 1;
  724.     col = 0;
  725.  
  726.     CO = 0;
  727.  
  728.     /* make sure these pixel coordinates are out of range */
  729.     old        = bad;
  730.     f_old = f_bad;
  731.  
  732.     /* copies pixels buffer to float type fraction buffer for fill purposes */
  733.     if(pot16bit)
  734.         if (set_pixel_buff(pixels,fraction,linelen))
  735.         {
  736.             EXIT_OVLY;
  737.             return(0);
  738.         }
  739.  
  740.   /*************************************************************************/
  741.   /* This section of code allows the operation of a preview mode when the    */
  742.   /* preview flag is set. Enabled, it allows the drawing of only the first */
  743.   /* line of the source image, then every 10th line, until and including    */
  744.   /* the last line. For the undrawn lines, only necessary calculations are */
  745.   /* made. As a bonus, in non-sphere mode a box is drawn to help visualize */
  746.   /* the effects of 3D transformations. Thanks to Marc Reinig for this idea*/
  747.   /* and code -- BTW, Marc did NOT put the goto in, but WE did, to avoid    */
  748.   /* copying code here, and to avoid a HUGE "if-then" construct. Besides,    */
  749.   /* we have ALREADY sinned, so why not sin some more?                            */
  750.   /*************************************************************************/
  751.  
  752.  
  753.     lastdot = min(xdots-1, linelen-1);
  754.     if (FILLTYPE >= 5)
  755.         if (haze && Targa_Out)
  756.         {
  757.             HAZE_MULT = haze * (
  758.                 (float)((long)(ydots - 1 - currow) *
  759.                 (long)(ydots - 1 - currow)) /
  760.                 (float)((long)(ydots - 1) * (long)(ydots - 1)));
  761.             HAZE_MULT = 100 - HAZE_MULT;
  762.         }
  763.  
  764.     if (previewfactor >= ydots || previewfactor > lastdot)
  765.         previewfactor = min ( ydots - 1, lastdot);
  766.  
  767.     localpreviewfactor = ydots/previewfactor;
  768.  
  769.     tout = 0;
  770.     /* Insure last line is drawn in preview and filltypes <0  */
  771.     if ((RAY || preview || FILLTYPE < 0) && (currow != ydots-1) &&
  772.         (currow % localpreviewfactor) && /* Draw mod preview lines */
  773.         !(!RAY && (FILLTYPE > 4) && (currow == 1)))
  774.             /* Get init geometry in lightsource modes */
  775.             goto reallythebottom; /* skip over most of the line3d calcs */
  776.     if (dotmode == 11)
  777.     {
  778.         char s[40];
  779.         sprintf(s,"mapping to 3d, reading line %d", currow);
  780.         dvid_status(1,s);
  781.     }
  782.  
  783.     if(!col && RAY && currow != 0)        start_object();
  784.  
  785.     if(FILLTYPE==0 && !SPHERE && !pot16bit && !RAY && debugflag != 2224 )
  786.         /* This while loop contains just a limited non-sphere case for speed */
  787.         /* Other while loop still has the old logic. Use debugflag to compare*/
  788.         while(col < linelen)
  789.         {
  790.             Real_Color = cur.color = pixels[col];
  791.             if (cur.color > 0 && cur.color < WATERLINE)
  792.                 Real_Color = cur.color = WATERLINE;  /* "lake" */
  793.             if(!usr_floatflag)
  794.             {
  795.                 lv0[0] = 0; /* don't save vector before perspective */
  796.  
  797.                 /* use 32-bit multiply math to snap this out */
  798.                 lv[0] = col;
  799.                 lv[0] = lv[0] << 16;
  800.                 lv[1] = currow;
  801.                 lv[1] = lv[1] << 16;
  802.                 lv[2] = cur.color;
  803.                 lv[2] = lv[2] << 16;
  804.  
  805.                 if(longvmultpersp(lv,lm,lv0,lv,lview,16) == -1)
  806.                 {
  807.                     cur    = bad;
  808.                     goto loopbottom;
  809.                 }
  810.                 cur.x = ((lv[0]/* +32768L */) >> 16) + xxadjust;
  811.                 cur.y = ((lv[1]/* +32768L */) >> 16) + yyadjust;
  812.             }
  813.             /* do in float if integer math overflowed */
  814.             if(usr_floatflag || overflow)
  815.             {
  816.                 /* slow float version for comparison */
  817.                 v[0] = col;
  818.                 v[1] = currow;
  819.                 v[2] = cur.color;
  820.                 mult_vec(v); /* matrix*vector routine */
  821.                 if(persp)
  822.                     perspective(v);
  823.                 cur.x = v[0] + xxadjust /* + .5 */;
  824.                 cur.y = v[1] + yyadjust /* + .5 */;
  825.             }
  826.             (*plot)(cur.x,cur.y,cur.color);
  827.             col++;
  828.         }  /*  End of while statement for plotting line  */
  829.     else
  830.  
  831.         /* PROCESS ROW LOOP BEGINS HERE */
  832.         while(col < linelen)
  833.         {
  834.             if ((RAY || preview || FILLTYPE < 0) &&
  835.                 (col != lastdot) &&        /* if this is not the last col */
  836.                 /* if not the 1st or mod factor col*/
  837.                 (col % (int)(aspect * localpreviewfactor)) &&
  838.                 (!(!RAY && FILLTYPE > 4 && col == 1)))
  839.                     goto loopbottom;
  840.  
  841.             f_cur.color = Real_Color = cur.color = pixels[col];
  842.  
  843.             if (RAY || preview || FILLTYPE < 0)
  844.             {
  845.                 next = col + aspect * localpreviewfactor;
  846.                 if (next == col)        next = col + 1;
  847.             }
  848.             else
  849.                 next = col + 1;
  850.             if (next >= lastdot)
  851.                 next = lastdot;
  852.  
  853.             if (cur.color > 0 && cur.color < WATERLINE)
  854.                 f_cur.color = Real_Color = cur.color = WATERLINE;        /* "lake" */
  855.             else if(pot16bit)
  856.                 f_cur.color += ((float)fraction[col])/(float)(1<<8);
  857.  
  858.             if(SPHERE) /* sphere case */
  859.             {
  860.                 sintheta = sinthetaarray[col];
  861.                 costheta = costhetaarray[col];
  862.  
  863.                 if(sinphi < 0 && !(RAY || FILLTYPE < 0))
  864.                 {
  865.                     cur    = bad;
  866.                     f_cur = f_bad;
  867.                     goto loopbottom;    /* another goto ! */
  868.                 }
  869.             /******************************************************************/
  870.             /* KEEP THIS FOR DOCS - original formula --                                */
  871.             /* if(rscale < 0.0)                                                                 */
  872.             /*            r = 1.0+((double)cur.color/(double)zcoord)*rscale;            */
  873.             /* else                                                                                */
  874.             /*            r = 1.0-rscale+((double)cur.color/(double)zcoord)*rscale;*/
  875.             /* R = (double)ydots/2;                                                            */
  876.             /* r = r*R;                                                                         */
  877.             /* cur.x = xdots/2 + sclx*r*sintheta*aspect + xup ;                    */
  878.             /* cur.y = ydots/2 + scly*r*costheta*cosphi - yup ;                    */
  879.             /******************************************************************/
  880.  
  881.                 if(rscale < 0.0)
  882.                     r = R + Rfactor*(double)f_cur.color*costheta;
  883.                 else if(rscale > 0.0)
  884.                     r = R -rXrscale + Rfactor*(double)f_cur.color*costheta;
  885.                 else
  886.                     r = R;
  887.                 if(persp || RAY) /* Allow Ray trace to go through so display is ok */
  888.                 {    /* mrr how do lv[] and cur and f_cur all relate */
  889.                     /* NOTE: fudge was pre-calculated above in r and R */
  890.                     /* (almost) guarantee negative */
  891.                     lv[2] = -R - r*costheta*sinphi;    /* z */
  892.                     if((lv[2] > zcutoff) && !FILLTYPE < 0)
  893.                     {
  894.                         cur = bad;
  895.                         f_cur = f_bad;
  896.                         goto loopbottom;    /* another goto ! */
  897.                     }
  898.                     lv[0] = xcenter + sintheta*sclx*r;    /* x */
  899.                     lv[1] = ycenter + costheta*cosphi*scly*r;        /* y */
  900.  
  901.                     if((FILLTYPE >= 5) || RAY)
  902.                     {  /* calculate illumination normal before persp */
  903.  
  904.                         r0        = r/65536;
  905.                         f_cur.x        = xcenter0 + sintheta*sclx*r0;
  906.                         f_cur.y        = ycenter0 + costheta*cosphi*scly*r0;
  907.                         f_cur.color = -r0*costheta*sinphi;
  908.                     }
  909.                     if(!(usr_floatflag || RAY))
  910.                     {
  911.                         if(longpersp(lv,lview,16) == -1)
  912.                         {
  913.                             cur = bad;
  914.                             f_cur = f_bad;
  915.                             goto loopbottom;    /* another goto ! */
  916.                         }
  917.                         cur.x = ((lv[0]+32768L) >> 16) + xxadjust;
  918.                         cur.y = ((lv[1]+32768L) >> 16) + yyadjust;
  919.                     }
  920.                     if(usr_floatflag || overflow || RAY)
  921.                     {
  922.                         v[0] = lv[0];
  923.                         v[1] = lv[1];
  924.                         v[2] = lv[2];
  925.                         v[0] /= fudge;
  926.                         v[1] /= fudge;
  927.                         v[2] /= fudge;
  928.                         perspective(v);
  929.                         cur.x = v[0]+.5 + xxadjust;
  930.                         cur.y = v[1]+.5 + yyadjust;
  931.                     }
  932.                 }
  933.                 else if (!(persp && RAY)) /* mrr Not sure how this and 3rd if
  934.                                                     above relate */
  935.                 {    /* mrr Why the xx- and yyadjust here and not above? */
  936.                     cur.x = f_cur.x = xcenter + sintheta*sclx*r + xxadjust;
  937.                     cur.y = f_cur.y = ycenter + costheta*cosphi*scly*r + yyadjust;
  938.                     if(FILLTYPE >= 5 || RAY) /* mrr why do we do this for filltype>5? */
  939.                         f_cur.color = -r * costheta * sinphi * sclz;
  940.                     v[0]=v[1]=v[2]=0;    /* MRR Why do we do this? */
  941.                 }
  942.             }
  943.             else /* non-sphere 3D */
  944.             {
  945.                 if(!usr_floatflag && !RAY)
  946.                 {
  947.                     if(FILLTYPE >= 5) /* flag to save vector before perspective */
  948.                         lv0[0] = 1;        /* in longvmultpersp calculation */
  949.                     else
  950.                         lv0[0] = 0;
  951.  
  952.                     /* use 32-bit multiply math to snap this out */
  953.                     lv[0] = col;
  954.                     lv[0] = lv[0] << 16;
  955.                     lv[1] = currow;
  956.                     lv[1] = lv[1] << 16;
  957.                     if(filetype || pot16bit) /* don't truncate fractional part */
  958.                         lv[2] = f_cur.color*65536.0;
  959.                     else    /* there IS no fractaional part here! */
  960.                     {
  961.                         lv[2] = f_cur.color;
  962.                         lv[2] = lv[2] << 16;
  963.                     }
  964.  
  965.                     if(longvmultpersp(lv,lm,lv0,lv,lview,16) == -1)
  966.                     {
  967.                         cur    = bad;
  968.                         f_cur = f_bad;
  969.                         goto loopbottom;
  970.                     }
  971.  
  972.                     cur.x = ((lv[0]+32768L) >> 16) + xxadjust;
  973.                     cur.y = ((lv[1]+32768L) >> 16) + yyadjust;
  974.                     if(FILLTYPE >= 5 && !overflow)
  975.                     {
  976.                         f_cur.x        = lv0[0];
  977.                         f_cur.x            /= 65536.0;
  978.                         f_cur.y        = lv0[1];
  979.                         f_cur.y            /= 65536.0;
  980.                         f_cur.color  = lv0[2];
  981.                         f_cur.color /= 65536.0;
  982.                     }
  983.                 }
  984.  
  985.                 if(usr_floatflag || overflow || RAY)
  986.                 /* do in float if integer math overflowed or doing Ray trace */
  987.                 {
  988.                     /* slow float version for comparison */
  989.                     v[0] = col;
  990.                     v[1] = currow;
  991.                     v[2] = f_cur.color; /* Actually the z value */
  992.  
  993.                     mult_vec(v); /* matrix*vector routine */
  994.  
  995.                     if (FILLTYPE > 4 || RAY)
  996.                     {
  997.                         f_cur.x    = v[0];
  998.                         f_cur.y    = v[1];
  999.                         f_cur.color = v[2];
  1000.  
  1001.                         if(RAY == 6)
  1002.                         {
  1003.                             f_cur.x = f_cur.x * (2.0 / xdots) - 1;
  1004.                             f_cur.y = f_cur.y * (2.0 / ydots) - 1;
  1005.                             f_cur.color = -f_cur.color * (2.0 / numcolors) - 1;
  1006.                         }
  1007.                     }
  1008.  
  1009.                     if(persp && !RAY)
  1010.                         perspective(v);
  1011.                     cur.x = v[0] + xxadjust + .5;
  1012.                     cur.y = v[1] + yyadjust + .5;
  1013.  
  1014.                     v[0] = 0;
  1015.                     v[1] = 0;
  1016.                     v[2] = WATERLINE;
  1017.                     mult_vec(v);
  1018.                     f_water = v[2];
  1019.                 }
  1020.             }
  1021.  
  1022.             if (RANDOMIZE)
  1023.                 if (cur.color > WATERLINE)
  1024.                 {
  1025.                     RND = rand15() >> 8;    /* 7-bit number */
  1026.                     RND = RND * RND >> rand_factor;    /* n-bit number */
  1027.  
  1028.                     if (rand() & 1)
  1029.                         RND = -RND; /* Make +/- n-bit number */
  1030.  
  1031.                     if ((int)(cur.color) + RND >= colors)
  1032.                         cur.color = colors-2;
  1033.                     else if ((int)(cur.color) + RND <= WATERLINE)
  1034.                         cur.color = WATERLINE + 1;
  1035.                     else
  1036.                         cur.color = cur.color + RND;
  1037.                     Real_Color = cur.color;
  1038.                 }
  1039.  
  1040.             if (RAY)
  1041.             {
  1042.                 if (col && currow &&
  1043.                     old.x > bad_check &&
  1044.                     old.x < (xdots - bad_check) &&
  1045.                     lastrow[col].x > bad_check &&
  1046.                     lastrow[col].y > bad_check &&
  1047.                     lastrow[col].x < (xdots - bad_check) &&
  1048.                     lastrow[col].y < (ydots - bad_check))
  1049.                 {
  1050.                     /* Get rid of all the triangles in the plane
  1051.                         at the base of the object */
  1052.  
  1053.                     if (f_cur.color == f_water &&
  1054.                         f_lastrow[col].color == f_water &&
  1055.                         f_lastrow[next].color == f_water)
  1056.                             goto loopbottom;
  1057.  
  1058.                     if (RAY != 6) /* Output the vertex info */
  1059.                         out_triangle(f_cur, f_old, f_lastrow[col],
  1060.                             cur.color, old.color, lastrow[col].color);
  1061.  
  1062.                     tout = 1;
  1063.  
  1064.                     draw_line (old.x, old.y, cur.x, cur.y, old.color);
  1065.                     draw_line (old.x, old.y, lastrow[col].x,
  1066.                         lastrow[col].y, old.color);
  1067.                     draw_line (lastrow[col].x, lastrow[col].y,
  1068.                         cur.x, cur.y, cur.color);
  1069.                     num_tris++;
  1070.                 }
  1071.  
  1072.                 if (col < lastdot && currow &&
  1073.                     lastrow[col].x > bad_check &&
  1074.                     lastrow[col].y > bad_check &&
  1075.                     lastrow[col].x < (xdots - bad_check) &&
  1076.                     lastrow[col].y < (ydots - bad_check) &&
  1077.                     lastrow[next].x > bad_check &&
  1078.                     lastrow[next].y > bad_check &&
  1079.                     lastrow[next].x < (xdots - bad_check) &&
  1080.                     lastrow[next].y < (ydots - bad_check))
  1081.                 {
  1082.                     /* Get rid of all the triangles in the plane
  1083.                     at the base of the object */
  1084.  
  1085.                     if (f_cur.color == f_water &&
  1086.                         f_lastrow[col].color == f_water &&
  1087.                         f_lastrow[next].color == f_water)
  1088.                             goto loopbottom;
  1089.  
  1090.                     if (RAY != 6) /* Output the vertex info */
  1091.                         out_triangle(f_cur, f_lastrow[col], f_lastrow[next],
  1092.                             cur.color, lastrow[col].color, lastrow[next].color);
  1093.  
  1094.                     tout = 1;
  1095.  
  1096.                     draw_line (lastrow[col].x, lastrow[col].y, cur.x, cur.y,
  1097.                         cur.color);
  1098.                     draw_line (lastrow[next].x, lastrow[next].y, cur.x, cur.y,
  1099.                         cur.color);
  1100.                     draw_line (lastrow[next].x, lastrow[next].y, lastrow[col].x,
  1101.                         lastrow[col].y, lastrow[col].color);
  1102.                     num_tris++;
  1103.                 }
  1104.  
  1105.                 if (RAY == 6)  /* Output vertex info for Acrospin */
  1106.                 {
  1107.                     fprintf (File_Ptr1, "% #4.4f % #4.4f % #4.4f R%dC%d\n",
  1108.                         f_cur.x, f_cur.y, f_cur.color, RO, CO);
  1109.                     if (CO > CO_MAX)
  1110.                         CO_MAX = CO;
  1111.                     CO++;
  1112.                 }
  1113.                 goto loopbottom;
  1114.  
  1115.             }
  1116.  
  1117.             switch(FILLTYPE)
  1118.             {
  1119.                 case -1:
  1120.                     if (col &&
  1121.                     old.x > bad_check &&
  1122.                     old.x < (xdots - bad_check))
  1123.                         draw_line (old.x, old.y, cur.x, cur.y, cur.color);
  1124.                     if (currow &&
  1125.                     lastrow[col].x > bad_check &&
  1126.                     lastrow[col].y > bad_check &&
  1127.                     lastrow[col].x < (xdots - bad_check) &&
  1128.                     lastrow[col].y < (ydots - bad_check))
  1129.                         draw_line (lastrow[col].x,lastrow[col].y,cur.x,
  1130.                             cur.y,cur.color);
  1131.                     break;
  1132.         
  1133.                 case 0:
  1134.                     (*plot)(cur.x,cur.y,cur.color);
  1135.                     break;
  1136.         
  1137.                 case 1:            /* connect-a-dot */
  1138.                     if ((old.x < xdots) && (col) &&
  1139.                         old.x > bad_check &&
  1140.                         old.y > bad_check) /* Don't draw from old to cur on col 0 */
  1141.                             draw_line(old.x,old.y,cur.x,cur.y,cur.color);
  1142.                     break;
  1143.         
  1144.                 case 2: /* with interpolation */
  1145.                 case 3: /* no interpolation */
  1146.                     /***************************************************************/
  1147.                     /*  "triangle fill" - consider four points: current point,        */
  1148.                     /*  previous point same row, point opposite current point in    */
  1149.                     /*  previous row, point after current point in previous row.    */
  1150.                     /*  The object is to fill all points inside the two triangles.    */
  1151.                     /*                                                                                    */
  1152.                     /*    lastrow[col].x/y___ lastrow[next]                                    */
  1153.                     /*              /    1         /                                                        */
  1154.                     /*            /        1       /                                                        */
  1155.                     /*            /        1     /                                                         */
  1156.                     /*  oldrow/col _____ trow/col                                                */
  1157.                     /***************************************************************/
  1158.         
  1159.                     if(currow && !col)
  1160.                         putatriangle(lastrow[next],lastrow[col],cur,cur.color);
  1161.                     if(currow && col)        /* skip first row and first column */
  1162.                     {
  1163.                         if(col == 1)
  1164.                             putatriangle(lastrow[col],oldlast,old,old.color);
  1165.         
  1166.                         if(col < lastdot)
  1167.                             putatriangle(lastrow[next],lastrow[col], cur, cur.color);
  1168.                         putatriangle(old, lastrow[col], cur, cur.color);
  1169.                     }
  1170.                     break;
  1171.         
  1172.                 case 4: /* "solid fill" */
  1173.                     if (SPHERE)
  1174.                     {
  1175.                         if (persp)
  1176.                         {
  1177.                             old.x = xcenter>>16;
  1178.                             old.y = ycenter>>16;
  1179.                         }
  1180.                         else
  1181.                         {
  1182.                             old.x = xcenter;
  1183.                             old.y = ycenter;
  1184.                         }
  1185.                     }
  1186.                     else
  1187.                     {
  1188.                         lv[0] = col;
  1189.                         lv[1] = currow;
  1190.                         lv[2] = 0;
  1191.         
  1192.                         /* apply fudge bit shift for integer math */
  1193.                         lv[0] = lv[0] << 16;
  1194.                         lv[1] = lv[1] << 16;
  1195.                         /* Since 0, unnecessary lv[2] = lv[2] << 16;*/
  1196.         
  1197.                         if(longvmultpersp(lv,lm,lv0,lv,lview,16))
  1198.                         {
  1199.                             cur    = bad;
  1200.                             f_cur = f_bad;
  1201.                             goto loopbottom;    /* another goto ! */
  1202.                         }
  1203.         
  1204.                         /*    Round and fudge back to original  */
  1205.                         old.x = (lv[0]+32768L) >> 16;
  1206.                         old.y = (lv[1]+32768L) >> 16;
  1207.                     }
  1208.                     if (old.x < 0)
  1209.                         old.x = 0;
  1210.                     if (old.x >= xdots)
  1211.                         old.x = xdots-1;
  1212.                     if (old.y < 0)
  1213.                         old.y = 0;
  1214.                     if (old.y >= ydots)
  1215.                         old.y = ydots-1;
  1216.                     draw_line(old.x,old.y,cur.x,cur.y,cur.color);
  1217.                     break;
  1218.         
  1219.                 case 5:
  1220.                 case 6:
  1221.                     /* light-source modulated fill */
  1222.                     if(currow && col)        /* skip first row and first column */
  1223.                     {
  1224.                         if(f_cur.color < bad_check || f_old.color < bad_check ||
  1225.                             f_lastrow[col].color < bad_check)
  1226.                                 break;
  1227.         
  1228.                         v1[0] = f_cur.x        - f_old.x;
  1229.                         v1[1] = f_cur.y        - f_old.y;
  1230.                         v1[2] = f_cur.color - f_old.color;
  1231.         
  1232.                         v2[0] = f_lastrow[col].x            - f_cur.x;
  1233.                         v2[1] = f_lastrow[col].y            - f_cur.y;
  1234.                         v2[2] = f_lastrow[col].color - f_cur.color;
  1235.         
  1236.                         cross_product (v1, v2, cross);
  1237.         
  1238.                         /* normalize cross - and check if non-zero */
  1239.                         if(normalize_vector(cross))
  1240.                         {
  1241.                             if(debugflag)
  1242.                             {
  1243.                                 static char far msg[] = {"debug, cur.color=bad"};
  1244.                                 stopmsg(0,msg);
  1245.                             }
  1246.                             cur.color = f_cur.color = bad.color;
  1247.                         }
  1248.                         else
  1249.                         {
  1250.                             /* line-wise averaging scheme */
  1251.                             if(LIGHTAVG>0)
  1252.                             {
  1253.                                 if(crossnotinit)
  1254.                                 {
  1255.                                     /* initialize array of old normal vectors */
  1256.                                     crossavg[0] = cross[0];
  1257.                                     crossavg[1] = cross[1];
  1258.                                     crossavg[2] = cross[2];
  1259.                                     crossnotinit = 0;
  1260.                                 }
  1261.                                 tmpcross[0] = (crossavg[0]*LIGHTAVG+cross[0]) /
  1262.                                    (LIGHTAVG+1);
  1263.                                 tmpcross[1] = (crossavg[1]*LIGHTAVG+cross[1]) /
  1264.                                    (LIGHTAVG+1);
  1265.                                 tmpcross[2] = (crossavg[2]*LIGHTAVG+cross[2]) /
  1266.                                    (LIGHTAVG+1);
  1267.             
  1268.                                 cross[0] = tmpcross[0];
  1269.                                 cross[1] = tmpcross[1];
  1270.                                 cross[2] = tmpcross[2];
  1271.  
  1272.                                 if(normalize_vector(cross))
  1273.                                 {
  1274.                                     /* this shouldn't happen */
  1275.                                     if(debugflag)
  1276.                                     {
  1277.                                         static char far msg[] =
  1278.                                         {"debug, normal vector err2"};
  1279.                                         stopmsg(0,msg);
  1280.                                         /* use next instead if you ever need details:
  1281.                                         static char far tmp[] = {"debug, vector err"};
  1282.                                         char msg[200];
  1283. #ifndef XFRACT
  1284.                                         sprintf(msg,"%Fs\n%f %f %f\n%f %f %f\n%f %f %f",
  1285. #else
  1286.                                         sprintf(msg,"%s\n%f %f %f\n%f %f %f\n%f %f %f",
  1287. #endif
  1288.                                         tmp, f_cur.x, f_cur.y, f_cur.color,
  1289.                                         f_lastrow[col].x, f_lastrow[col].y,
  1290.                                         f_lastrow[col].color, f_lastrow[col-1].x,
  1291.                                         f_lastrow[col-1].y,f_lastrow[col-1].color);
  1292.                                         stopmsg(0,msg);
  1293.                                         */
  1294.                                     }
  1295.                                     cur.color = f_cur.color = colors;
  1296.                                 }
  1297.                             }
  1298.                             crossavg[0] = tmpcross[0];
  1299.                             crossavg[1] = tmpcross[1];
  1300.                             crossavg[2] = tmpcross[2];
  1301.  
  1302.                             /* dot product of unit vectors is cos of angle between */
  1303.                             /* we will use this value to shade surface */
  1304.         
  1305.                             cur.color = 1 + (colors-2) *
  1306.                                 (1.0-dot_product(cross,light_direction));
  1307.                         }
  1308.                         /* if colors out of range, set them to min or max color 
  1309.                             index but avoid background index. This makes colors
  1310.                             "opaque" so SOMETHING plots. These conditions shouldn't 
  1311.                             happen but just in case                    */
  1312.                         if(cur.color < 1)            /* prevent transparent colors */
  1313.                             cur.color = 1;        /* avoid background */
  1314.                         if(cur.color > colors-1)
  1315.                             cur.color = colors-1;
  1316.         
  1317.                     /* why "col < 2"? So we have sufficient geometry for the fill */
  1318.                     /* algorithm, which needs previous point in same row to have  */
  1319.                     /* already been calculated (variable old)        */
  1320.                     /* fix ragged left margin in preview */
  1321.                         if (col == 1 && currow > 1)
  1322.                             putatriangle(lastrow[next],lastrow[col],cur,cur.color);
  1323.         
  1324.                         if(col < 2 || currow < 2) /* don't have valid colors yet */
  1325.                             break;
  1326.         
  1327.                         if(col < lastdot)
  1328.                             putatriangle(lastrow[next],lastrow[col],cur,cur.color);
  1329.                         putatriangle(old,lastrow[col],cur,cur.color);
  1330.         
  1331.                         plot=standardplot;
  1332.                     }
  1333.                     break;
  1334.             }  /*    End of CASE statement for fill type  */
  1335.         
  1336. loopbottom:
  1337.  
  1338.             if (RAY || (FILLTYPE != 0 && FILLTYPE != 4))
  1339.             {
  1340.                 /* for triangle and grid fill purposes */
  1341.                 oldlast = lastrow[col];
  1342.                 old = lastrow[col] = cur;
  1343.         
  1344.                 /* for illumination model purposes */
  1345.                 f_old    = f_lastrow[col] = f_cur;
  1346.                 if (currow && RAY && col >= lastdot)
  1347.                 /* if we're at the end of a row, close the object */
  1348.                 {
  1349.                     end_object(tout);
  1350.                     tout=0;
  1351.                     if (ferror (File_Ptr1))
  1352.                     {
  1353.                         fclose (File_Ptr1);
  1354.                         remove (light_name);
  1355.                         File_Error(ray_name, 2);
  1356.                         EXIT_OVLY;
  1357.                         return(-1);
  1358.                     }
  1359.                 }
  1360.             }
  1361.         
  1362.             col++;
  1363.  
  1364.         }  /*  End of while statement for plotting line  */
  1365.  
  1366.     RO++;
  1367.  
  1368. reallythebottom:
  1369.         
  1370.     /* stuff that HAS to be done, even in preview mode, goes here */    
  1371.     if(SPHERE)    
  1372.     {    
  1373.         /* incremental sin/cos phi calc */    
  1374.         if(currow == 0)    
  1375.         {    
  1376.             sinphi = oldsinphi2;    
  1377.             cosphi = oldcosphi2;    
  1378.         }    
  1379.         else    
  1380.         {    
  1381.             sinphi = twocosdeltaphi*oldsinphi2 - oldsinphi1;    
  1382.             cosphi = twocosdeltaphi*oldcosphi2 - oldcosphi1;    
  1383.             oldsinphi1 = oldsinphi2;    
  1384.             oldsinphi2 = sinphi;    
  1385.             oldcosphi1 = oldcosphi2;    
  1386.             oldcosphi2 = cosphi;    
  1387.         }    
  1388.     }
  1389.     EXIT_OVLY;
  1390.     return(0); /* decoder needs to know all is well !!! */
  1391. }
  1392.  
  1393.  
  1394. /* vector version of line draw */
  1395. static void _fastcall vdraw_line(v1,v2,color)
  1396. double *v1,*v2;
  1397. int color;
  1398. {
  1399.     int x1,y1,x2,y2;
  1400.     x1 = (int)v1[0];
  1401.     y1 = (int)v1[1];
  1402.     x2 = (int)v2[0];
  1403.     y2 = (int)v2[1];
  1404.     draw_line(x1,y1,x2,y2,color);
  1405. }
  1406.  
  1407.  
  1408.  
  1409. static void corners(m,show,pxmin,pymin,pzmin,pxmax,pymax,pzmax)
  1410.  
  1411. MATRIX m;
  1412. int show; /* turns on box-showing feature */
  1413. double *pxmin,*pymin,*pzmin,*pxmax,*pymax,*pzmax;
  1414.  
  1415. {
  1416.     int i,j;
  1417.     VECTOR S[2][4]; /* Holds the top an bottom points, S[0][]=bottom */
  1418.  
  1419.     /*
  1420.     define corners of box fractal is in in x,y,z plane
  1421.     "b" stands for "bottom" - these points are the corners of the screen
  1422.     in the x-y plane. The "t"'s stand for Top - they are the top of
  1423.     the cube where 255 color points hit.
  1424.     */
  1425.  
  1426.     *pxmin = *pymin = *pzmin = (int)INT_MAX;
  1427.     *pxmax = *pymax = *pzmax = (int)INT_MIN; 
  1428.  
  1429.     for (j = 0; j < 4; ++j)
  1430.         for (i=0;i<3;i++)
  1431.             S[0][j][i]=S[1][j][i]=0;
  1432.  
  1433.     S[0][1][0] = S[0][2][0] = S[1][1][0] = S[1][2][0] = xdots-1;
  1434.     S[0][2][1] = S[0][3][1] = S[1][2][1] = S[1][3][1] = ydots-1;
  1435.     S[1][0][2] = S[1][1][2] = S[1][2][2] = S[1][3][2] = zcoord-1;
  1436.  
  1437.     for (i = 0; i < 4; ++i)
  1438.     {
  1439.         /* transform points */
  1440.         vmult(S[0][i],m,S[0][i]);
  1441.         vmult(S[1][i],m,S[1][i]);
  1442.  
  1443.         /* update minimums and maximums */
  1444.         if (S[0][i][0] <= *pxmin) *pxmin = S[0][i][0];
  1445.         if (S[0][i][0] >= *pxmax) *pxmax = S[0][i][0];
  1446.         if (S[1][i][0] <= *pxmin) *pxmin = S[1][i][0];
  1447.         if (S[1][i][0] >= *pxmax) *pxmax = S[1][i][0];
  1448.         if (S[0][i][1] <= *pymin) *pymin = S[0][i][1];
  1449.         if (S[0][i][1] >= *pymax) *pymax = S[0][i][1];
  1450.         if (S[1][i][1] <= *pymin) *pymin = S[1][i][1];
  1451.         if (S[1][i][1] >= *pymax) *pymax = S[1][i][1];
  1452.         if (S[0][i][2] <= *pzmin) *pzmin = S[0][i][2];
  1453.         if (S[0][i][2] >= *pzmax) *pzmax = S[0][i][2];
  1454.         if (S[1][i][2] <= *pzmin) *pzmin = S[1][i][2];
  1455.         if (S[1][i][2] >= *pzmax) *pzmax = S[1][i][2];
  1456.     }
  1457.  
  1458.     if(show)
  1459.     {
  1460.         if(persp)
  1461.         {
  1462.             for (i=0;i<4;i++)
  1463.             {
  1464.                 perspective(S[0][i]);
  1465.                 perspective(S[1][i]);
  1466.             }
  1467.         }
  1468.  
  1469.         /* Keep the box surrounding the fractal */
  1470.         for (j=0;j<2;j++)
  1471.             for (i = 0; i < 4; ++i)
  1472.             {
  1473.                 S[j][i][0] += xxadjust;
  1474.                 S[j][i][1] += yyadjust;
  1475.             }
  1476.  
  1477.         draw_rect(S[0][0],S[0][1],S[0][2],S[0][3],2,1);/* Bottom */
  1478.  
  1479.         draw_rect(S[0][0],S[1][0],S[0][1],S[1][1], 5, 0); /* Sides */
  1480.         draw_rect(S[0][2],S[1][2],S[0][3],S[1][3], 6, 0);
  1481.  
  1482.         draw_rect(S[1][0],S[1][1],S[1][2],S[1][3],8,1); /* Top */
  1483.     }
  1484. }
  1485.  
  1486.  
  1487.  
  1488. /* This function draws a vector from origin[] to direct[] and a box
  1489.     around it. The vector and box are transformed or not depending on
  1490.     FILLTYPE.
  1491.  
  1492. */
  1493.  
  1494. static void draw_light_box (origin, direct, light_m)
  1495. double *origin, *direct;
  1496. MATRIX light_m;
  1497.  
  1498.  
  1499. {
  1500.     VECTOR S[2][4];
  1501.     int i,j;
  1502.     double temp;
  1503.  
  1504.     S[1][0][0] = S[0][0][0] = origin[0];
  1505.     S[1][0][1] = S[0][0][1] = origin[1];
  1506.  
  1507.     S[1][0][2] = direct[2];
  1508.  
  1509.     for (i=0;i<2;i++)
  1510.     {
  1511.         S[i][1][0] = S[i][0][0];
  1512.         S[i][1][1] = direct[1];
  1513.         S[i][1][2] = S[i][0][2];
  1514.         S[i][2][0] = direct[0];
  1515.         S[i][2][1] = S[i][1][1];
  1516.         S[i][2][2] = S[i][0][2];
  1517.         S[i][3][0] = S[i][2][0];
  1518.         S[i][3][1] = S[i][0][1];
  1519.         S[i][3][2] = S[i][0][2];
  1520.     }
  1521.  
  1522.     /* transform the corners if necessary */
  1523.     if (FILLTYPE == 6)
  1524.         for (i=0;i<4;i++)
  1525.         {
  1526.             vmult (S[0][i],light_m,S[0][i]);
  1527.             vmult (S[1][i],light_m,S[1][i]);
  1528.         }
  1529.  
  1530.     /* always use perspective to aid viewing */
  1531.     temp = view[2]; /* save perspective distance for a later restore */
  1532.     view[2] = - P * 300.0 / 100.0;
  1533.  
  1534.     for (i=0;i<4;i++)
  1535.     {
  1536.         perspective(S[0][i]);
  1537.         perspective(S[1][i]);
  1538.     }
  1539.     view[2] = temp; /* Restore perspective distance*/
  1540.  
  1541.     /* Adjust for aspect */
  1542.     for (i=0;i<4;i++)
  1543.     {
  1544.         S[0][i][0] = S[0][i][0] * aspect;
  1545.         S[1][i][0] = S[1][i][0] * aspect;
  1546.     }
  1547.  
  1548.     /* draw box connecting transformed points. NOTE order and COLORS */
  1549.     draw_rect(S[0][0],S[0][1],S[0][2],S[0][3],2,1);
  1550.  
  1551.     vdraw_line (S[0][0],S[1][2],8);
  1552.  
  1553.     /* sides */
  1554.     draw_rect(S[0][0],S[1][0],S[0][1],S[1][1], 4, 0);
  1555.     draw_rect(S[0][2],S[1][2],S[0][3],S[1][3], 5, 0);
  1556.  
  1557.     draw_rect(S[1][0],S[1][1],S[1][2],S[1][3],3,1);
  1558.  
  1559.     /* Draw the "arrow head" */
  1560.     for (i= -3;i<4;i++)
  1561.         for (j= -3;j<4;j++)
  1562.             if (abs(i) + abs(j) < 6)
  1563.                 plot((int)(S[1][2][0]+i),(int)(S[1][2][1]+j),10);
  1564. }
  1565.  
  1566.  
  1567.  
  1568. static void draw_rect (V0, V1, V2, V3, color, rect)
  1569.  
  1570. VECTOR V0, V1, V2, V3;
  1571. int color, rect;
  1572.  
  1573. {
  1574. VECTOR V[4];
  1575. int i;
  1576.  
  1577.     for (i=0;i<2;i++) 
  1578.     { /* Since V[2] is not used by vdraw_line don't bother setting it */    
  1579.         V[0][i] = V0[i];    
  1580.         V[1][i] = V1[i];    
  1581.         V[2][i] = V2[i];    
  1582.         V[3][i] = V3[i];    
  1583.     }    
  1584.     if (rect) /* Draw a rectangle */
  1585.     {
  1586.         for (i=0;i<4;i++)
  1587.             if (fabs(V[i][0]-V[(i+1)%4][0]) < -2*bad_check &&
  1588.                 fabs(V[i][1]-V[(i+1)%4][1]) < -2*bad_check)
  1589.                     vdraw_line (V[i],V[(i+1)%4],color);
  1590.     }
  1591.     else /* Draw 2 lines instead */
  1592.     {
  1593.         for(i=0;i<3;i+=2)
  1594.             if (fabs(V[i][0]-V[i+1][0]) < -2*bad_check &&
  1595.                 fabs(V[i][1]-V[i+1][1]) < -2*bad_check)
  1596.                     vdraw_line (V[i],V[i+1],color);
  1597.     }
  1598.     return;
  1599. }
  1600.  
  1601.  
  1602.  
  1603. /* replacement for plot - builds a table of min and max x's instead of plot */
  1604. /* called by draw_line as part of triangle fill routine */
  1605. static void _fastcall putminmax(int x,int y,int color)
  1606. {
  1607.     if(y >= 0 && y < ydots)
  1608.     {
  1609.         if(x < minmax_x[y].minx) minmax_x[y].minx = x;
  1610.         if(x > minmax_x[y].maxx) minmax_x[y].maxx = x;
  1611.     }
  1612. }
  1613.  
  1614. /*
  1615.     This routine fills in a triangle. Extreme left and right values for
  1616.     each row are calculated by calling the line function for the sides.
  1617.     Then rows are filled in with horizontal lines
  1618. */
  1619. #define MAXOFFSCREEN  2 /* allow two of three points to be off screen */
  1620.  
  1621. static void _fastcall putatriangle(struct point pt1,struct point pt2,
  1622.                     struct point pt3,int color)
  1623. {
  1624.     extern struct point p1,p2,p3;
  1625.     int miny,maxy;
  1626.     int x,y,xlim;
  1627.  
  1628.     /* Too many points off the screen? */
  1629.     if(offscreen(pt1) + offscreen(pt2) + offscreen(pt3) > MAXOFFSCREEN)
  1630.         return;
  1631.  
  1632.     p1 = pt1; /* needed by interpcolor */
  1633.     p2 = pt2;
  1634.     p3 = pt3;
  1635.  
  1636.     /* fast way if single point or single line */
  1637.     if (p1.y == p2.y && p1.x == p2.x)
  1638.     {
  1639.         plot = fillplot;
  1640.         if (p1.y == p3.y && p1.x == p3.x)
  1641.             (*plot)(p1.x, p1.y, color);
  1642.         else
  1643.             draw_line(p1.x,p1.y,p3.x,p3.y,color);
  1644.         plot = normalplot;
  1645.         return;
  1646.     }
  1647.     else if ( (p3.y == p1.y && p3.x == p1.x) || (p3.y == p2.y && p3.x == p2.x) )
  1648.     {
  1649.         plot = fillplot;
  1650.         draw_line(p1.x,p1.y,p2.x,p2.y,color);
  1651.         plot = normalplot;
  1652.         return;
  1653.     }
  1654.  
  1655.     /* find min max y */
  1656.     miny = maxy = p1.y;
  1657.     if(p2.y < miny) miny = p2.y;
  1658.     else         maxy = p2.y;
  1659.     if(p3.y < miny) miny = p3.y;
  1660.     else if(p3.y > maxy) maxy = p3.y;
  1661.  
  1662.     /* only worried about values on screen */
  1663.     if(miny < 0)        miny = 0;
  1664.     if(maxy >= ydots) maxy = ydots-1;
  1665.  
  1666.     for(y=miny;y<=maxy;y++)
  1667.     {
  1668.         minmax_x[y].minx = (int)INT_MAX;
  1669.         minmax_x[y].maxx = (int)INT_MIN;
  1670.     }
  1671.  
  1672.     /* set plot to "fake" plot function */
  1673.     plot = putminmax;
  1674.  
  1675.     /* build table of extreme x's of triangle */
  1676.     draw_line(p1.x,p1.y,p2.x,p2.y,0);
  1677.     draw_line(p2.x,p2.y,p3.x,p3.y,0);
  1678.     draw_line(p3.x,p3.y,p1.x,p1.y,0);
  1679.  
  1680.     for(y=miny;y<=maxy;y++)
  1681.     {
  1682.         xlim = minmax_x[y].maxx;
  1683.         for(x=minmax_x[y].minx;x<=xlim;x++)
  1684.         (*fillplot)(x,y,color);
  1685.     }
  1686.     plot = normalplot;
  1687. }
  1688.  
  1689.  
  1690. static int _fastcall offscreen(struct point pt)
  1691. {
  1692.     if(pt.x >= 0)
  1693.         if(pt.x < xdots)
  1694.             if(pt.y >= 0)
  1695.                 if(pt.y < ydots)
  1696.                     return(0); /* point is ok */
  1697.     if (abs(pt.x) > 0-bad_check || abs(pt.y) > 0-bad_check)
  1698.         return(99); /* point is bad */
  1699.     return(1); /* point is off the screen */
  1700. }
  1701.  
  1702. static void _fastcall clipcolor(int x,int y,int color)
  1703. {
  1704.     if(0 <= x    && x < xdots    &&
  1705.         0 <= y    && y < ydots    &&
  1706.         0 <= color && color < filecolors)
  1707.     {
  1708.         standardplot(x,y,color);
  1709.  
  1710.         if (Targa_Out)
  1711.             if (!(glassestype==1 || glassestype==2)) /* standardplot modifies color in these types */
  1712.                 targa_color(x, y, color);
  1713.     }
  1714. }
  1715.  
  1716. /*********************************************************************/
  1717. /* This function is the same as clipcolor but checks for color being */
  1718. /* in transparent range. Intended to be called only if transparency  */
  1719. /* has been enabled.                                                 */
  1720. /*********************************************************************/
  1721.  
  1722. static void _fastcall T_clipcolor(int x,int y,int color)
  1723. {
  1724.     if (0 <= x        && x < xdots            && /*  is the point on screen?  */
  1725.         0 <= y    && y < ydots            && /*  Yes?  */
  1726.         0 <= color && color < colors    && /*  Colors in valid range?  */
  1727.         /*  Lets make sure its not a transparent color  */
  1728.         (transparent[0] > color || color > transparent[1]))
  1729.     {
  1730.         standardplot(x,y,color); /* I guess we can plot then  */
  1731.  
  1732.         if (Targa_Out)
  1733.             if (!(glassestype==1 || glassestype==2)) /* standardplot modifies color in these types */
  1734.                 targa_color(x, y, color);
  1735.     }
  1736. }
  1737.  
  1738. /************************************************************************/
  1739. /* A substitute for plotcolor that interpolates the colors according    */
  1740. /* to the x and y values of three points (p1,p2,p3) which are static in    */
  1741. /* this routine                                                            */
  1742. /*                                                                        */
  1743. /*    In Light source modes, color is light value, not actual color        */
  1744. /*    Real_Color always contains the actual color                            */
  1745. /************************************************************************/
  1746.  
  1747. static void _fastcall interpcolor(int x,int y,int color)
  1748. {
  1749.     int D,d1,d2,d3;
  1750.  
  1751.   /* this distance formula is not the usual one - but it has the virtue
  1752.         that it uses ONLY additions (almost) and it DOES go to zero as the
  1753.         points get close.
  1754.         */
  1755.  
  1756.     d1 = abs(p1.x-x)+abs(p1.y-y);
  1757.     d2 = abs(p2.x-x)+abs(p2.y-y);
  1758.     d3 = abs(p3.x-x)+abs(p3.y-y);
  1759.  
  1760.     D = (d1 + d2 + d3) << 1;
  1761.     if(D)
  1762.     {  /* calculate a weighted average of colors -
  1763.         long casts prevent integer overflow. This can evaluate to zero */
  1764.         color = ((long)(d2+d3)*(long)p1.color +
  1765.             (long)(d1+d3)*(long)p2.color +
  1766.             (long)(d1+d2)*(long)p3.color) / D;
  1767.     }
  1768.     
  1769.     if(0 <= x        && x < xdots    &&
  1770.         0 <= y        && y < ydots    &&
  1771.         0 <= color && color < colors &&
  1772.         (transparent[1] == 0 || Real_Color > transparent[1] ||
  1773.         transparent[0] > Real_Color))
  1774.     {
  1775.         if (Targa_Out)
  1776.             if (!(glassestype==1 || glassestype==2)) /* standardplot modifies color in these types */
  1777.                 D = targa_color(x, y, color);
  1778.  
  1779.         if (FILLTYPE >= 5)
  1780.             if (Real_V && Targa_Out)
  1781.                 color = D;
  1782.             else
  1783.                         {
  1784.                             color =  (1 + (unsigned)color * IAmbient)/256;
  1785.                             if (color == 0)
  1786.                                 color = 1;
  1787.                         }
  1788.         standardplot(x,y,color);
  1789.     }
  1790. }
  1791.  
  1792.  
  1793.  
  1794. /*
  1795.     In non light source modes, both color and Real_Color contain the
  1796.     actual pixel color. In light source modes, color contains the
  1797.     light value, and Real_Color contains the origninal color
  1798.  
  1799.     This routine takes a pixel modifies it for lightshading if appropriate
  1800.     and plots it in a Targa file. Used in plot3d.c
  1801. */
  1802.  
  1803. int _fastcall targa_color(int x,int y,int color)
  1804. {
  1805.     unsigned long H, S, V;
  1806.     BYTE RGB[3];
  1807.  
  1808.     if (FILLTYPE == 2 || glassestype==1 || glassestype==2)  
  1809.         Real_Color = color; /* So Targa gets interpolated color */
  1810.  
  1811.     RGB[0]  =  dacbox [Real_Color] [0] << 2; /* Move color space to */
  1812.     RGB[1]  =  dacbox [Real_Color] [1] << 2; /* 256 color primaries */
  1813.     RGB[2]  =  dacbox [Real_Color] [2] << 2; /* from 64 colors */
  1814.  
  1815.     /* Now lets convert it to HSV */
  1816.     R_H(RGB[0], RGB[1], RGB[2], &H, &S, &V);
  1817.  
  1818.     /* Modify original S and V components */
  1819.     if (FILLTYPE > 4 && !(glassestype==1 || glassestype==2)) /* Adjust for Ambient */
  1820.         V = (V * (65535 - (unsigned)(color * IAmbient))) / 65535;
  1821.  
  1822.     if (haze)
  1823.     {
  1824.         S = (unsigned long)(S * HAZE_MULT) / 100; /* Haze lowers sat of colors */
  1825.         if (V >= 32640) /* Haze reduces contrast */
  1826.         {
  1827.             V = V - 32640;
  1828.             V = (unsigned long)((V * HAZE_MULT) / 100);
  1829.             V = V + 32640;
  1830.         }
  1831.         else
  1832.         {
  1833.             V = 32640 - V;
  1834.             V = (unsigned long)((V * HAZE_MULT) / 100);
  1835.             V = 32640 - V;
  1836.         }
  1837.     }
  1838.     /* Now lets convert it back to RGB. Original Hue, modified Sat and Val */
  1839.     H_R(&RGB[0], &RGB[1], &RGB[2], H, S, V);
  1840.  
  1841.     if (Real_V)
  1842.         V = (35 * (int)RGB[0] + 45 * (int)RGB[1] + 20 * (int)RGB[2]) / 100;
  1843.  
  1844.     /* Now write the color triple to its transformed location */
  1845.     /* on the disk. */
  1846.     targa_writedisk (x+sxoffs, y+syoffs, RGB[0], RGB[1], RGB[2]);
  1847.  
  1848.     return(255-V);
  1849. }
  1850.  
  1851.  
  1852.  
  1853. static int set_pixel_buff(BYTE *pixels,BYTE far *fraction,unsigned linelen)
  1854. {
  1855.     int i;
  1856.     if ((evenoddrow++ & 1) == 0) /* even rows are color value */
  1857.     {
  1858.         for(i=0;i<linelen;i++) /* add the fractional part in odd row */
  1859.             fraction[i] = pixels[i];
  1860.         return(1);
  1861.     }
  1862.     else /* swap */
  1863.     {
  1864.         BYTE tmp;
  1865.         for(i=0;i<linelen;i++) /* swap so pixel has color */
  1866.         {
  1867.             tmp = pixels[i];
  1868.             pixels[i]=fraction[i];
  1869.             fraction[i]=tmp;
  1870.         }
  1871.     }
  1872.     return(0);
  1873. }
  1874.  
  1875.  
  1876. /* cross product  - useful because cross is perpendicular to v and w */
  1877. /**** PB commented this out - it is unused
  1878. static int chk_cross_product (int col, int row,VECTOR v, VECTOR w, VECTOR cross, VECTOR crossavg)
  1879. {
  1880.     static start = 1;
  1881.     static FILE *fp;
  1882.  
  1883.     if(start)
  1884.     {
  1885.         fp = fopen("blob","w");
  1886.         start = 0;
  1887.     }
  1888.  
  1889.     fprintf(fp,"row %+4d col %+4d v1 %+8.3e %+8.3e %+8.3e v2 %+8.3e %+8.3e %+8.3e cross %+8.3e %+8.3e %+8.3e crossavg %+8.3e %+8.3e %+8.3e \n",
  1890.     row,col,v[0],v[1],v[2],w[0],w[1],w[2],cross[0],cross[1],cross[2],crossavg[0],crossavg[1],crossavg[2]);
  1891.     return(0);
  1892. }
  1893. ***/
  1894.  
  1895. /**************************************************************************
  1896.  
  1897.         Common routine for printing error messages to the screen for Targa
  1898.         and other files
  1899.  
  1900. **************************************************************************/
  1901.  
  1902.  
  1903. #ifndef XFRACT
  1904. static char f[]                 = "%Fs%Fs";
  1905. static char fff[]               = "%Fs%Fs%Fs";
  1906. #else
  1907. static char f[]                 = "%s%s";
  1908. static char fff[]               = "%s%s%s";
  1909. #endif
  1910. static char far OOPS[]  = {"OOPS, "};
  1911. static char far E1[]        = {"can't handle this type of file.\n"};
  1912. static char far str1[]  = {"couldn't open  < "};
  1913. static char far str3[]  = {"image wrong size\n"};
  1914. static char far temp1[] = {"ran out of disk space. < "};
  1915.  
  1916. static void File_Error (char *File_Name1, int ERROR)
  1917. {
  1918.    char msgbuf[200];
  1919.  
  1920.     error = ERROR;
  1921.     switch(ERROR)
  1922.     {
  1923.     case 1: /* Can't Open */
  1924. #ifndef XFRACT
  1925.                 sprintf(msgbuf,"%Fs%Fs%s >", OOPS, str1, File_Name1);
  1926. #else
  1927.                 sprintf(msgbuf,"%s%s%s >", OOPS, str1, File_Name1);
  1928. #endif
  1929.         break;
  1930.     case 2: /* Not enough room */
  1931. #ifndef XFRACT
  1932.         sprintf(msgbuf,"%Fs%Fs%s >", OOPS, temp1, File_Name1);
  1933. #else
  1934.                 sprintf(msgbuf,"%s%s%s >", OOPS, temp1, File_Name1);
  1935. #endif
  1936.         break;
  1937.     case 3: /* Image wrong size */
  1938.         sprintf(msgbuf, f, OOPS, str3);
  1939.         break;
  1940.     case 4: /* Wrong file type */
  1941.         sprintf(msgbuf, f, OOPS, E1);
  1942.         break;
  1943.     }
  1944.     stopmsg(0,msgbuf);
  1945.     return;
  1946. }
  1947.  
  1948.  
  1949. /************************************************************************/
  1950. /*                                                                        */
  1951. /*        This function opens a TARGA_24 file for reading and writing. If    */
  1952. /*        its a new file, (overlay == 0) it writes a header. If it is to    */
  1953. /*        overlay an existing file (overlay == 1) it copies the original    */
  1954. /*        header whose lenght and validity was determined in                */
  1955. /*        Targa_validate.                                                    */
  1956. /*                                                                        */
  1957. /*        It Verifies there is enough disk space, and leaves the file     */
  1958. /*        at the start of the display data area.                            */
  1959. /*                                                                        */
  1960. /*        If this is an overlay, closes source and copies to "targa_temp"    */
  1961. /*        If there is an error close the file.                             */
  1962. /*                                                                        */
  1963. /* **********************************************************************/
  1964.  
  1965.  
  1966. static int startdisk1 (char *File_Name2, FILE *Source, int overlay)
  1967. {
  1968.     int i,j,k, inc;
  1969.     FILE *fps;
  1970.  
  1971.     /* Open File for both reading and writing */
  1972.     if ((fps=fopen(File_Name2,"w+b"))==NULL)
  1973.     {
  1974.         File_Error(File_Name2, 1);
  1975.         return(-1); /* Oops, somethings wrong! */
  1976.     }
  1977.  
  1978.     inc = 1; /* Assume we are overlaying a file */
  1979.  
  1980.     /* Write the header */
  1981.     if (overlay) /* We are overlaying a file */
  1982.         for (i=0;i<T_header_24;i++) /* Copy the header from the Source */
  1983.             fputc(fgetc(Source),fps);
  1984.     else
  1985.     {    /* Write header for a new file */
  1986.         /* ID field size = 0, No color map, Targa type 2 file */
  1987.         for (i=0;i<12;i++)
  1988.         {
  1989.             if (i == 2)
  1990.                 fputc(i,fps);
  1991.             else
  1992.                 fputc(0,fps);
  1993.         }
  1994.         /*  Write image size  */
  1995.         for (i=0;i<4;i++)
  1996.             fputc(upr_lwr[i],fps);
  1997.         fputc(T24,fps); /* Targa 24 file */
  1998.         fputc(T32,fps); /* Image at upper left */
  1999.         inc = 3;
  2000.     }
  2001.  
  2002.     /*  Finished with the header, now lets work on the display area  */
  2003.     for (i=0;i<ydots;i++)    /* "clear the screen" (write to the disk) */
  2004.     {
  2005.         for (j=0;j<line_length1;j=j+inc)
  2006.         {
  2007.             if (overlay)
  2008.                 fputc(fgetc(Source), fps);
  2009.             else
  2010.                 for (k=2;k>-1;k--)
  2011.                     fputc(back_color[k], fps);            /* Targa order (B, G, R) */
  2012.         }
  2013.         if (ferror (fps))        
  2014.         {        
  2015.             /*  Almost certainly not enough disk space  */        
  2016.             fclose (fps);
  2017.             fclose (Source);
  2018.             remove (File_Name2);        
  2019.             File_Error(File_Name2, 2);        
  2020.             return(-2);        
  2021.         }
  2022.         if (check_key())        return(-3);
  2023.     }
  2024.  
  2025.     if (targa_startdisk(fps, T_header_24) != 0)
  2026.     {
  2027.         enddisk();
  2028.         remove (File_Name2);
  2029.         return(-4);
  2030.     }
  2031.     return(0);
  2032. }
  2033.  
  2034. /**************************************************************************
  2035.  
  2036.  
  2037. **************************************************************************/
  2038.  
  2039. int targa_validate(char *File_Name)
  2040. {
  2041.     FILE *fp;
  2042.     int i, j = 0;
  2043.  
  2044.     /* Attempt to open source file for reading */
  2045.     if ((fp=fopen(File_Name,"rb"))==NULL)
  2046.     {
  2047.         File_Error(File_Name, 1);
  2048.         return(-1); /* Oops, file does not exist */
  2049.     }
  2050.  
  2051.     T_header_24 += fgetc(fp); /* Check ID field and adjust header size */
  2052.  
  2053.     if (fgetc(fp)) /* Make sure this is an unmapped file */
  2054.     {
  2055.         File_Error(File_Name, 4);
  2056.         return(-1);
  2057.     }
  2058.  
  2059.     if (fgetc(fp)!=2) /* Make sure it is a type 2 file */
  2060.     {
  2061.         File_Error(File_Name, 4);
  2062.         return(-1);
  2063.     }
  2064.  
  2065.     /* Skip color map specification */
  2066.     for (i=0;i<5;i++)
  2067.             fgetc(fp);
  2068.  
  2069.     for (i=0;i<4;i++)
  2070.     {
  2071.         /* Check image origin */
  2072.         fgetc(fp);
  2073.         if(j != 0)
  2074.         {
  2075.             File_Error(File_Name, 4);
  2076.             return(-1);
  2077.         }
  2078.     }
  2079.     /* Check Image specs */
  2080.     for (i=0;i<4;i++)
  2081.         if(fgetc(fp) != upr_lwr[i])
  2082.         {
  2083.             File_Error(File_Name,3);
  2084.             return(-1);
  2085.         }
  2086.  
  2087.     if(fgetc(fp) != T24) error=4; /* Is it a targa 24 file? */
  2088.     if(fgetc(fp) != T32) error=4; /* Is the origin at the upper left? */
  2089.     if (error == 4)
  2090.     {
  2091.         File_Error(File_Name,4);
  2092.         return(-1);
  2093.     }
  2094.     rewind(fp);
  2095.  
  2096.     /* Now that we know its a good file, create a working copy */
  2097.     if (startdisk1(targa_temp, fp, 1))
  2098.         return(-1);
  2099.     
  2100.     fclose(fp);    /* Close the source */
  2101.  
  2102.     T_Safe=1; /* Original file successfully copied to targa_temp */
  2103.     return(0);
  2104. }
  2105.  
  2106. static int R_H (R, G, B, H, S, V)
  2107. BYTE R,G,B;
  2108. unsigned long *H, *S, *V;
  2109. {
  2110.     unsigned long    R1, G1, B1, DENOM;
  2111.     BYTE MIN;
  2112.  
  2113.     *V = R;
  2114.     MIN = G;
  2115.     if (R < G)
  2116.     {
  2117.         *V = G;
  2118.         MIN = R;
  2119.         if (G < B)            *V = B;
  2120.         if (B < R)            MIN = B;
  2121.     }
  2122.     else
  2123.     {
  2124.         if (B < G)            MIN = B;
  2125.         if (R < B)            *V = B;
  2126.     }
  2127.     DENOM = *V - MIN;
  2128.     if (*V != 0 && DENOM !=0)
  2129.     {
  2130.         *S = ((DENOM << 16) / *V) - 1;
  2131.     }
  2132.     else  *S = 0;/* Color is black! and Sat has no meaning */
  2133.     if(*S == 0) /*  R=G=B => shade of grey and Hue has no meaning */
  2134.     {
  2135.         *H = 0;
  2136.         *V = *V << 8;
  2137.         return(1);  /* v or s or both are 0 */
  2138.     }
  2139.     if (*V == MIN)
  2140.     {
  2141.         *H = 0;
  2142.         *V = *V << 8;
  2143.         return(0);
  2144.     }
  2145.     R1 = (((*V - R) * 60) << 6) / DENOM;        /* distance of color from red    */
  2146.     G1 = (((*V - G) * 60) << 6) / DENOM;        /* distance of color from green */
  2147.     B1 = (((*V - B) * 60) << 6) / DENOM;        /* distance of color from blue  */
  2148.     if(*V == R)
  2149.         if (MIN == G)        *H = (300 << 6) + B1;
  2150.         else            *H = (60 << 6) - G1;
  2151.     if(*V == G)
  2152.         if (MIN == B)        *H = (60 << 6) + R1;
  2153.         else            *H = (180 << 6) - B1;
  2154.     if(*V == B)
  2155.         if(MIN == R)        *H = (180 << 6) + G1;
  2156.         else            *H = (300 << 6) - R1;
  2157.  
  2158.     *V = *V << 8;
  2159.     return(0);
  2160. }
  2161.  
  2162. static int H_R (R, G, B, H, S, V)
  2163. BYTE *R, *G, *B;
  2164. unsigned long  H, S, V;
  2165. {
  2166.     unsigned long        P1, P2, P3;
  2167.     int    RMD, I;
  2168.  
  2169.     if(H >= 23040)            H = H % 23040; /*  Makes h circular  */
  2170.     I = H / 3840;
  2171.     RMD = H % 3840;            /*  RMD = fractional part of H    */
  2172.  
  2173.     P1 = ((V * (65535 - S)) / 65280) >> 8;
  2174.     P2 = (((V * (65535 - (S * RMD) / 3840)) / 65280) - 1) >> 8;
  2175.     P3 = (((V * (65535 - (S * (3840 - RMD)) / 3840)) / 65280)) >> 8;
  2176.     V = V >> 8;
  2177.     switch (I)
  2178.     {
  2179.     case 0:
  2180.         *R = V;
  2181.         *G = P3;
  2182.         *B = P1;
  2183.         break;
  2184.     case 1:
  2185.         *R = P2;
  2186.         *G = V;
  2187.         *B = P1;
  2188.         break;
  2189.     case 2:
  2190.         *R = P1;
  2191.         *G = V;
  2192.         *B = P3;
  2193.         break;
  2194.     case 3:
  2195.         *R = P1;
  2196.         *G = P2;
  2197.         *B = V;
  2198.         break;
  2199.     case 4:
  2200.         *R = P3;
  2201.         *G = P1;
  2202.         *B = V;
  2203.         break;
  2204.     case 5:
  2205.         *R = V ;
  2206.         *G = P1;
  2207.         *B = P2;
  2208.         break;
  2209.     }
  2210.     return(0);
  2211. }
  2212.  
  2213.  
  2214. /***************************************************************************/
  2215. /*                                        */
  2216. /* EB & DG fiddled with outputs for Rayshade so they work. with v4.x.      */
  2217. /* EB == eli brandt.     ebrandt@jarthur.claremont.edu                                          */
  2218. /* DG == dan goldwater.  daniel_goldwater@brown.edu & dgold@math.umass.edu */
  2219. /*    (NOTE: all the stuff we fiddled with is commented with "EB & DG" (plus even some extra bonus comments!) */
  2220. /* general raytracing code info/notes:                         */
  2221. /*                                            */
  2222. /*  ray == 0 means no raytracer output    ray == 7 is for dxf                    */
  2223. /*  ray == 1 is for dkb/pov        ray == 4 is for mtv            */
  2224. /*  ray == 2 is for vivid        ray == 5 is for rayshade        */
  2225. /*  ray == 3 is for raw            ray == 6 is for acrospin        */
  2226. /*                                          */
  2227. /*  rayshade needs counterclockwise triangles.  raytracers that support     */
  2228. /*  the 'heightfield' primitive include rayshade and pov.  anyone want to write */
  2229. /*  code to make heightfields?  they are *MUCH* faster to trace than triangles  */
  2230. /*  when doing landscapes...                            */
  2231. /*  */
  2232. /*  stuff EB & DG changed:  */
  2233. /*  made the rayshade output create a "grid" aggregate object (one of rayshade's primitives), instead */
  2234. /*  of a global grid.  as a result, the grid can be optimized based on the number of triangles.  */
  2235. /*  the z component of the grid can always be 1 since the surface formed by the triangles is flat */
  2236. /*  (ie, it doesnt curve over itself).  this is a major optimization.  the x and y grid size is */
  2237. /*  also optimized for a 4:3 aspect ratio image, to get the fewest possible traingles in each grid square. */
  2238. /*  also, we fixed the rayshade code so it actually produces output that works with rayshade. */
  2239. /*  (maybe the old code was for a really old version of rayshade?).  */
  2240. /*  */
  2241. /*  */
  2242. /***************************************************************************/
  2243.  
  2244. /********************************************************************/
  2245. /*                                                                    */
  2246. /*  This routine writes a header to a ray tracer data file. It        */
  2247. /*  Identifies the version of FRACTINT which created it an the        */
  2248. /*  key 3D parameters in effect at the time.                        */
  2249. /*                                                                    */
  2250. /********************************************************************/
  2251.  
  2252.  
  2253. static char far declare[] = {"DECLARE    "};
  2254. static char far frac_default[] = {"F_Dflt"};
  2255. static char far color[] = {"COLOR  "};
  2256. static char far dflt[] = {"RED 0.8 GREEN 0.4 BLUE 0.1\n"};
  2257. static char far d_color[] = {"0.8 0.4 0.1"};
  2258. static char far r_surf[] = {"0.95 0.05 5 0 0\n"};
  2259. static char far surf[] = {"surf={diff="};
  2260. static char far rs_surf[] = {"applysurf diffuse "};   /* EB & DG: changed "surface T" to "applysurf" and "diff" to "diffuse" */
  2261. static char far end[] = {"END_"};
  2262. static char far plane[] = {"PLANE"};
  2263. static char far m1[] = {"-1.0 "};
  2264. static char far one[] = {" 1.0 "};
  2265. static char far z[]  = {" 0.0 "};
  2266. static char far bnd_by[]  = {" BOUNDED_BY\n"};
  2267. static char far end_bnd[]  = {" END_BOUND\n"};
  2268. static char far inter[]  = {"INTERSECTION\n"};
  2269. #ifndef XFRACT
  2270. static char fmt[] = "   %Fs <%Fs%Fs%Fs> % #4.3f %Fs%Fs\n";
  2271. #else
  2272. static char fmt[] = "   %s <%s%s%s> % #4.3f %s%s\n";
  2273. #endif
  2274. static char dxf_begin[] = {"  0\nSECTION\n  2\nTABLES\n  0\nTABLE\n  2\nLAYER\n\
  2275.  70\n     2\n  0\nLAYER\n  2\n0\n 70\n     0\n 62\n     7\n  6\nCONTINUOUS\n\
  2276.   0\nLAYER\n  2\nFRACTAL\n 70\n    64\n 62\n     1\n  6\nCONTINUOUS\n  0\n\
  2277. ENDTAB\n  0\nENDSEC\n  0\nSECTION\n  2\nENTITIES\n"};
  2278. static char dxf_3dface[] = {"  0\n3DFACE\n  8\nFRACTAL\n 62\n%3d\n"};
  2279. static char dxf_vertex[] = {"%3d\n%g\n"};
  2280. static char dxf_end[] = {"  0\nENDSEC\n  0\nEOF\n"};
  2281.  
  2282. static char far composite[] = {"COMPOSITE"};
  2283. static char far object[]  = {"OBJECT"};
  2284. static char far triangle[] = {"TRIANGLE "};
  2285. static char far l_tri[] = {"triangle"};
  2286. static char far texture[] = {"TEXTURE\n"};
  2287. /* static char far end_texture[] = {" END_TEXTURE\n"}; */
  2288. static char far red[] = {"RED"};
  2289. static char far green[] = {"GREEN"};
  2290. static char far blue[] = {"BLUE"};
  2291.  
  2292. static char far frac_texture[] = {"    AMBIENT 0.25 DIFFUSE 0.75"};
  2293.  
  2294. static char far polygon[] = {"polygon={points=3;"};
  2295. static char far vertex[] = {" vertex =  "};
  2296. static char far d_vert[] = {"    <"};
  2297. static char f1[] = "% #4.4f ";
  2298. /* EB & DG: changed this to much better values. now it actually makes a good trace */
  2299. static char far grid[] = {"screen 640 480\neyep 0 2.1 0.8\nlookp 0 0 -0.95\nlight 1 point -2 1 1.5\n"};
  2300. static char far grid2[] = {"background .3 0 0\nreport verbose\n"};
  2301.  
  2302. static char n[] = "\n";
  2303. static char f2[] = "R%dC%d R%dC%d\n";
  2304. static char far ray_comment1[] = {"/* make a gridded aggregate. this size grid is fast for landscapes. */\n"};
  2305. static char far ray_comment2[] = {"/* make z grid = 1 always for landscapes. */\n\n"};
  2306. static char far grid3[] = {"grid 33 25 1\n"};
  2307.  
  2308.  
  2309. static int _fastcall RAY_Header(void)
  2310.  
  2311.  
  2312. {  /* Open the ray tracing output file */
  2313.     check_writefile(ray_name,".ray");
  2314.     if ((File_Ptr1=fopen(ray_name,"w"))==NULL)
  2315.         return(-1); /* Oops, somethings wrong! */
  2316.  
  2317.     if (RAY == 2)
  2318.         fprintf(File_Ptr1, "//");
  2319.     if (RAY == 4)
  2320.         fprintf(File_Ptr1, "#");
  2321.     if (RAY == 5)
  2322.         fprintf(File_Ptr1, "/*\n");
  2323.     if (RAY == 6)
  2324.         fprintf(File_Ptr1, "--");
  2325.       if (RAY == 7)
  2326.           fprintf(File_Ptr1, dxf_begin);
  2327.   
  2328.       if (RAY != 7)
  2329.          fprintf(File_Ptr1, banner, s3, release/100., s3a);
  2330.  
  2331.     if (RAY == 5)
  2332.         fprintf(File_Ptr1, "*/\n");
  2333.  
  2334.  
  2335.     /* Set the default color */
  2336.     if (RAY == 1)
  2337.     {
  2338.         fprintf (File_Ptr1, f, declare, frac_default);
  2339.         fprintf (File_Ptr1, " = ");
  2340.         fprintf (File_Ptr1, f, color, dflt);
  2341.     }
  2342.     if (BRIEF)
  2343.     {
  2344.         if (RAY == 2)
  2345.         {
  2346.             fprintf (File_Ptr1, f, surf, d_color);
  2347.             fprintf (File_Ptr1, ";}\n");
  2348.         }
  2349.         if (RAY == 4)
  2350.         {
  2351.             fprintf (File_Ptr1, "f ");
  2352.             fprintf (File_Ptr1, f, d_color, r_surf);
  2353.         }
  2354.         if (RAY == 5)
  2355.             fprintf (File_Ptr1, f, rs_surf, d_color);
  2356.     }
  2357.       if (RAY != 7)
  2358.         fprintf (File_Ptr1, n);
  2359.  
  2360.     if (RAY == 5)             /* EB & DG: open "grid" opject, a speedy way to do aggregates in rayshade */
  2361.         fprintf (File_Ptr1, fff, ray_comment1,ray_comment2,grid3);
  2362.  
  2363.     if (RAY == 6)
  2364. #ifndef XFRACT
  2365.                 fprintf (File_Ptr1, "%Fs", acro_s1);
  2366. #else
  2367.         fprintf (File_Ptr1, "%s", acro_s1);
  2368. #endif
  2369.  
  2370.     return(0);
  2371. }
  2372.  
  2373.  
  2374. /********************************************************************/
  2375. /*                                                                    */
  2376. /*  This routine describes the triangle to the ray tracer, it        */
  2377. /*  sets the color of the triangle to the average of the color        */
  2378. /*  of its verticies and sets the light parameters to arbitrary        */
  2379. /*  values.                                                            */
  2380. /*                                                                    */
  2381. /*  Note: numcolors (number of colors in the source                    */
  2382. /*  file) is used instead of colors (number of colors avail. with    */
  2383. /*  display) so you can generate ray trace files with your LCD        */
  2384. /*  or monochrome display                                            */
  2385. /*                                                                    */
  2386. /********************************************************************/
  2387.  
  2388. static int _fastcall out_triangle(struct f_point pt1, struct f_point pt2,
  2389.             struct f_point pt3, int c1, int c2, int c3)
  2390.  
  2391. {
  2392. int i, j;
  2393. float c[3];
  2394. float pt_t[3][3];
  2395.  
  2396.     /* Normalize each vertex to screen size and adjust coordinate system */
  2397.     pt_t[0][0]            =    2 * pt1.x            / xdots  - 1;
  2398.     pt_t[0][1]            =  (2 * pt1.y            / ydots  - 1);
  2399.     pt_t[0][2]            =  -2 * pt1.color / numcolors - 1;
  2400.     pt_t[1][0]            =    2 * pt2.x            / xdots  - 1;
  2401.     pt_t[1][1]            =  (2 * pt2.y            / ydots  - 1);
  2402.     pt_t[1][2]            =  -2 * pt2.color / numcolors - 1;
  2403.     pt_t[2][0]            =    2 * pt3.x            / xdots  - 1;
  2404.     pt_t[2][1]            =  (2 * pt3.y            / ydots  - 1);
  2405.     pt_t[2][2]            =  -2 * pt3.color / numcolors - 1;
  2406.  
  2407.     /* Color of triangle is average of colors of its verticies */
  2408.     if (!BRIEF)
  2409.         for (i=0;i<=2;i++)
  2410.         c[i] = (float)(dacbox[c1][i] + dacbox[c2][i] + dacbox[c3][i])
  2411.                 / (3 * 63);
  2412.  
  2413.         /* get rid of degenerate triangles: any two points equal */
  2414.         if (pt_t[0][0] == pt_t[1][0] &&
  2415.                 pt_t[0][1] == pt_t[1][1] &&
  2416.                 pt_t[0][2] == pt_t[1][2] ||
  2417.  
  2418.                 pt_t[0][0] == pt_t[2][0] &&
  2419.                 pt_t[0][1] == pt_t[2][1] &&
  2420.                 pt_t[0][2] == pt_t[2][2] ||
  2421.  
  2422.                 pt_t[2][0] == pt_t[1][0] &&
  2423.                 pt_t[2][1] == pt_t[1][1] &&
  2424.                 pt_t[2][2] == pt_t[1][2])
  2425.             return(0);
  2426.  
  2427.     /* Describe the triangle */
  2428. #ifndef XFRACT
  2429.     if (RAY == 1)
  2430.         fprintf (File_Ptr1, " %Fs\n  %Fs", object, triangle);
  2431.         if (RAY == 2 && !BRIEF)
  2432.         fprintf (File_Ptr1, "%Fs", surf);
  2433. #else
  2434.     if (RAY == 1)
  2435.         fprintf (File_Ptr1, " %s\n  %s", object, triangle);
  2436.         if (RAY == 2 && !BRIEF)
  2437.         fprintf (File_Ptr1, "%s", surf);
  2438. #endif
  2439.     if (RAY == 4 && !BRIEF)
  2440.         fprintf (File_Ptr1, "f");
  2441.     if (RAY == 5 && !BRIEF)
  2442. #ifndef XFRACT
  2443.         fprintf (File_Ptr1, "%Fs", rs_surf);
  2444. #else
  2445.         fprintf (File_Ptr1, "%s", rs_surf);
  2446. #endif
  2447.  
  2448.     if (!BRIEF && RAY != 1 && RAY != 7)
  2449.         for (i=0;i<=2;i++)
  2450.         fprintf (File_Ptr1, f1, c[i]);
  2451.  
  2452.     if (RAY == 2)
  2453.     {
  2454.         if (!BRIEF)
  2455.         fprintf (File_Ptr1, ";}\n");
  2456. #ifndef XFRACT
  2457.         fprintf (File_Ptr1, "%Fs", polygon);
  2458. #else
  2459.         fprintf (File_Ptr1, "%s", polygon);
  2460. #endif
  2461.     }
  2462.     if (RAY == 4)
  2463.     {
  2464.         if (!BRIEF)
  2465. #ifndef XFRACT
  2466.             fprintf (File_Ptr1, "%Fs", r_surf);
  2467. #else
  2468.             fprintf (File_Ptr1, "%s", r_surf);
  2469. #endif
  2470.         fprintf (File_Ptr1, "p 3");
  2471.     }
  2472.     if (RAY == 5)
  2473.     {
  2474.         if (!BRIEF)
  2475.             fprintf (File_Ptr1, n);
  2476. #ifndef XFRACT
  2477.         fprintf (File_Ptr1, "%Fs", l_tri);   /* EB & DG: removed "T" after "triangle" */
  2478. #else
  2479.         fprintf (File_Ptr1, "%s", l_tri);    /* EB & DG: removed "T" after "triangle" */
  2480. #endif
  2481.     }
  2482.  
  2483.       if (RAY == 7)
  2484.           fprintf (File_Ptr1, dxf_3dface, min(255, max(1, c1)));
  2485.  
  2486.     for(i=0;i<=2;i++)  /*  Describe each  Vertex  */
  2487.     {
  2488.           if (RAY != 7)
  2489.         fprintf (File_Ptr1, n);
  2490.  
  2491. #ifndef XFRACT
  2492.         if (RAY == 1)
  2493.             fprintf (File_Ptr1, "%Fs", d_vert);
  2494.         if (RAY == 2)
  2495.             fprintf (File_Ptr1, "%Fs", vertex);
  2496. #else
  2497.         if (RAY == 1)
  2498.             fprintf (File_Ptr1, "%s", d_vert);
  2499.         if (RAY == 2)
  2500.             fprintf (File_Ptr1, "%s", vertex);
  2501. #endif
  2502.         if (RAY > 3 && RAY != 7)
  2503.             fprintf (File_Ptr1, " ");
  2504.  
  2505.         for(j=0;j<=2;j++)
  2506.                {
  2507.               if (RAY == 7)
  2508.                   {
  2509.                   /* write 3dface entity to dxf file */
  2510.                   fprintf (File_Ptr1, dxf_vertex, 10*(j+1)+i, pt_t[i][j]);
  2511.                   if (i == 2)                /* 3dface needs 4 vertecies */
  2512.                       fprintf (File_Ptr1, dxf_vertex, 10*(j+1)+i+1, pt_t[i][j]);
  2513.                   }
  2514.               else if (!(RAY == 4 || RAY == 5))
  2515.                   fprintf (File_Ptr1, f1, pt_t[i][j]); /* Right handed */
  2516.               else
  2517.                   fprintf (File_Ptr1, f1, pt_t[2-i][j]); /* Left handed */
  2518.               }
  2519.  
  2520.         if (RAY == 1)
  2521.         fprintf (File_Ptr1, ">");
  2522.         if (RAY == 2)
  2523.         fprintf (File_Ptr1, ";");
  2524.     }
  2525.  
  2526.     if (RAY == 1)
  2527.     {
  2528. #ifndef XFRACT
  2529.         fprintf (File_Ptr1, " %Fs%Fs\n", end, triangle);
  2530. #else
  2531.         fprintf (File_Ptr1, " %s%s\n", end, triangle);
  2532. #endif
  2533.         if (!BRIEF)
  2534.         {
  2535. #ifndef XFRACT
  2536.         fprintf (File_Ptr1, "  %Fs"
  2537.             "    %Fs%Fs% #4.4f %Fs% #4.4f %Fs% #4.4f\n"
  2538.             "%Fs"
  2539.             " %Fs%Fs",
  2540. #else
  2541.         fprintf (File_Ptr1,
  2542.             "  %s   %s%s% #4.4f %s% #4.4f %s% #4.4f\n%s %s%s",
  2543. #endif
  2544.             texture,
  2545.             color, red, c[0], green, c[1], blue, c[2],
  2546.             frac_texture,
  2547.             end, texture);
  2548.         }
  2549. #ifndef XFRACT
  2550.         fprintf (File_Ptr1, "  %Fs%Fs  %Fs%Fs",
  2551. #else
  2552.         fprintf (File_Ptr1, "  %s%s  %s%s",
  2553. #endif
  2554.         color, frac_default,
  2555.         end, object);
  2556.         triangle_bounds(pt_t); /* update bounding info */
  2557.     }
  2558.     if (RAY == 2)
  2559.         fprintf (File_Ptr1, "}");
  2560.     if (RAY == 3 && !BRIEF)
  2561.         fprintf (File_Ptr1, n);
  2562.  
  2563.       if (RAY != 7)
  2564.         fprintf (File_Ptr1, n);
  2565.  
  2566.     return(0);
  2567. }
  2568.  
  2569.  
  2570. /********************************************************************/
  2571. /*                                                                    */
  2572. /*  This routine calculates the min and max values of a triangle    */
  2573. /*  for use in creating ray tracer data files. The values of min    */
  2574. /*  and max x, y, and z are assumed to be global.                    */
  2575. /*                                                                    */
  2576. /********************************************************************/
  2577.  
  2578. static void _fastcall triangle_bounds(float pt_t[3][3])
  2579.  
  2580. {
  2581. int i,j;
  2582.  
  2583.     for (i=0;i<=2;i++)
  2584.     for (j=0;j<=2;j++)
  2585.     {
  2586.         if(pt_t[i][j] < min_xyz[j]) min_xyz[j] = pt_t[i][j];
  2587.         if(pt_t[i][j] > max_xyz[j]) max_xyz[j] = pt_t[i][j];
  2588.     }
  2589.     return;
  2590. }
  2591.  
  2592. /********************************************************************/
  2593. /*                                                                    */
  2594. /*  This routine starts a composite object for ray trace data files.*/
  2595. /*                                                                    */
  2596. /********************************************************************/
  2597.  
  2598. static int _fastcall start_object(void)
  2599.  
  2600. {
  2601.     if (RAY != 1)            return(0);
  2602.  
  2603.     /*    Reset the min/max values, for bounding box  */
  2604.     min_xyz[0] = min_xyz[1] = min_xyz[2] =  999999;
  2605.     max_xyz[0] = max_xyz[1] = max_xyz[2] = -999999;
  2606.  
  2607. #ifndef XFRACT
  2608.     fprintf (File_Ptr1, "%Fs\n", composite);
  2609. #else
  2610.     fprintf (File_Ptr1, "%s\n", composite);
  2611. #endif
  2612.     return(0);
  2613. }
  2614.  
  2615. /********************************************************************/
  2616. /*                                                                    */
  2617. /*  This routine adds a bounding box for the triangles drawn        */
  2618. /*  in the last block and completes the composite object created.    */
  2619. /*  It uses the globals min and max x,y and z calculated in            */
  2620. /*  z calculated in Triangle_Bounds().                                */
  2621. /*                                                                    */
  2622. /********************************************************************/
  2623.  
  2624. static int _fastcall end_object(int triout)
  2625. {
  2626.       if (RAY == 7)
  2627.           return(0);
  2628.     if (RAY == 1)
  2629.     {
  2630.     if (triout)
  2631.         {
  2632.         /* Make sure the bounding box is slightly larger than the object */
  2633.         int i;
  2634.         for (i=0;i<=2;i++)
  2635.         {
  2636.             if (min_xyz[i] == max_xyz[i])
  2637.             {
  2638.                 min_xyz[i] -= 0.01;
  2639.             max_xyz[i] += 0.01;
  2640.             }
  2641.             else
  2642.             {
  2643.                 min_xyz[i] -= (max_xyz[i] - min_xyz[i]) * 0.01;
  2644.                 max_xyz[i] += (max_xyz[i] - min_xyz[i]) * 0.01;
  2645.             }
  2646.         }
  2647.  
  2648.         /* Add the bounding box info */
  2649. #ifndef XFRACT
  2650.         fprintf (File_Ptr1, "%Fs  %Fs", bnd_by, inter);
  2651. #else
  2652.         fprintf (File_Ptr1, "%s  %s", bnd_by, inter);
  2653. #endif
  2654.         fprintf (File_Ptr1, fmt, plane,m1,z,z,-min_xyz[0],end,plane);
  2655.         fprintf (File_Ptr1, fmt, plane,one,z,z,max_xyz[0],end,plane);
  2656.         fprintf (File_Ptr1, fmt, plane,z,m1,z,-min_xyz[1],end,plane);
  2657.         fprintf (File_Ptr1, fmt, plane,z,one,z,max_xyz[1],end,plane);
  2658.         fprintf (File_Ptr1, fmt, plane,z,z,m1,-min_xyz[2],end,plane);
  2659.         fprintf (File_Ptr1, fmt, plane,z,z,one,max_xyz[2],end,plane);
  2660. #ifndef XFRACT
  2661.         fprintf (File_Ptr1, "  %Fs%Fs%Fs", end, inter, end_bnd);
  2662. #else
  2663.         fprintf (File_Ptr1, "  %s%s%s", end, inter, end_bnd);
  2664. #endif
  2665.         }
  2666.  
  2667.         /* Complete the composite object statement */
  2668. #ifndef XFRACT
  2669.         fprintf (File_Ptr1, "%Fs%Fs\n", end, composite);
  2670. #else
  2671.         fprintf (File_Ptr1, "%s%s\n", end, composite);
  2672. #endif
  2673.     }
  2674.  
  2675.     if (RAY!=6 && RAY!=5)
  2676.         fprintf (File_Ptr1, n);  /* EB & DG: too many newlines */
  2677.  
  2678.     return(0);
  2679. }
  2680.  
  2681.  
  2682. static void line3d_cleanup()
  2683. {
  2684.  int i,j;
  2685.     if(RAY && File_Ptr1)
  2686.     {  /*  Finish up the ray tracing files */
  2687.         static char far n_ta[] ={"{ No. Of Triangles = "};
  2688.         if (RAY != 5 && RAY != 7)
  2689.             fprintf (File_Ptr1, n);  /* EB & DG: too many newlines */
  2690.         if (RAY == 2)
  2691.             fprintf(File_Ptr1, "\n\n//");
  2692.         if (RAY == 4)
  2693.             fprintf(File_Ptr1, "\n\n#");
  2694.  
  2695.         if (RAY == 5)
  2696. #ifndef XFRACT
  2697.             fprintf (File_Ptr1, "end\n\n/*good landscape:*/\n%Fs%Fs\n/*", grid,grid2); /* EB & DG: end grid aggregate */
  2698. #else
  2699.             fprintf (File_Ptr1, "end\n\n/*good landscape:*/\n%s%s\n/*", grid,grid2);  /* EB & DG: end grid aggregate */
  2700. #endif
  2701.         if (RAY == 6)
  2702.         {
  2703. #ifndef XFRACT
  2704.             fprintf (File_Ptr1, "%Fs", acro_s2);
  2705. #else
  2706.             fprintf (File_Ptr1, "%s", acro_s2);
  2707. #endif
  2708.             for (i=0;i<RO;i++)
  2709.                 for (j=0;j<=CO_MAX;j++)
  2710.                 {
  2711.                     if (j < CO_MAX)
  2712.                         fprintf (File_Ptr1, f2, i, j, i, j+1);
  2713.                     if (i < RO - 1)
  2714.                         fprintf (File_Ptr1, f2, i, j, i+1, j);
  2715.                     if (i && i < RO && j < CO_MAX)
  2716.                         fprintf (File_Ptr1, f2, i, j, i-1, j+1);
  2717.                 }
  2718.             fprintf (File_Ptr1, "\n\n--");
  2719.         }
  2720.             if (RAY != 7)
  2721. #ifndef XFRACT
  2722.             fprintf(File_Ptr1, "%Fs%d }*/\n\n",n_ta, num_tris); /* EB & DG: this is what s3a should be */
  2723. /* see note        fprintf(File_Ptr1, "%Fs%d%Fs",n_ta, num_tris, s3a);   BUG! s3a=null here! why?! */
  2724. #else
  2725.             fprintf(File_Ptr1, "%s%d }*/\n\n",n_ta, num_tris);  /* EB & DG: this is what s3a should be */
  2726. /* see note        fprintf(File_Ptr1, "%s%d%s",n_ta, num_tris, s3a);     BUG! s3a=null here! why?! */
  2727. #endif
  2728.           if (RAY == 7)
  2729.                fprintf (File_Ptr1, dxf_end);
  2730.         fclose(File_Ptr1);
  2731.         File_Ptr1 = NULL;
  2732.     }
  2733.     if (Targa_Out)
  2734.     {    /*  Finish up targa files */
  2735.         T_header_24 = 18; /* Reset Targa header size */
  2736.         enddisk();
  2737.         if (!debugflag && T_Safe && !error && Targa_Overlay)
  2738.         {
  2739.             remove(light_name);
  2740.             rename(targa_temp,light_name);
  2741.         }
  2742.         if (!debugflag && Targa_Overlay)
  2743.             remove (targa_temp);
  2744.     }
  2745.     usr_floatflag &= 1; /* strip second bit */
  2746.     error = T_Safe = 0;
  2747. }
  2748.  
  2749.