home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / mondello / tritemp.h < prev    next >
C/C++ Source or Header  |  1996-05-27  |  13KB  |  440 lines

  1. /* 
  2.  * file: tritemp.h
  3.  * auth: Peter McDermott
  4.  * desc: template for triangle functions 
  5.  *  
  6.  * This is by far the most complicated algorithm I've ever had to create
  7.  * and implement.  I'm graduating in 2 weeks and am now convinced that I
  8.  * should have taken Numerical Analysis and Algorithms instead of Chinese,
  9.  * and Networks.
  10.  *
  11.  * As it stands now, this function _STILL_ doesn't draw triangles correctly.
  12.  * In fact, most of the time it's off by a pixel at at least one of the
  13.  * end points.  It will hopefully be fixed shortly.
  14.  *
  15.  * #define's:
  16.  *   OPCODE        actual opcode the 5470 is sent (in color-indexed mode)
  17.  *   OPCODE1       opcode sent to 5470 for red & green banks in rgba mode
  18.  *   OPCODE2       opcode sent to 5470 for blue bank in rgba mode 
  19.  *   FLAT_INDEX    flat shaded, 8bpp
  20.  *   INTERP_INDEX  gouraud shaded, 8pp
  21.  *   FLAT_COLOR    flat shaded, 24 bpp
  22.  *   INTERP_COLOR  gouraud shaded 24bpp
  23.  *   NOVB       function passes args as x1, y1, etc instead of three 
  24.  *                 vertices v1, v2, v3
  25.  *
  26.  *  The six trianges:
  27.  *
  28.  *  left to right rendering:
  29.  *
  30.  *                         \                      /\
  31.  *    |\                   \ \                   /..\
  32.  *    | \                   \..\                /....\
  33.  *    |  \                   \...\             /......\
  34.  *    |   \                   \...|           /........\
  35.  *     |  /                    \..|          /......../
  36.  *     | /                      \..|        /...../
  37.  *     |/                        \.|       /../         
  38.  *                                \|      /.  
  39.  *
  40.  *
  41.  * right to left rendering:
  42.  *  
  43.  */
  44.  
  45. /* #define DEBUG_TRITEMP_H */ 
  46.  
  47. {
  48.  
  49.    uint min, mid, max;
  50.  
  51.    int dy_main, dx_main;
  52.    int count1, span1, rung1, count2, span2, rung2, px, width, t1, t2;
  53.    int rungmain,dxm,wbp,dw,wopp,dwopp,xbp;  
  54.    int tf; int i;
  55.  
  56. #ifdef INTERP_COLOR
  57.    int rmin,gmin,bmin, rmid,gmid,bmid, rmax,gmax,bmax;
  58. #endif
  59.  
  60. #ifdef NOVB
  61.    /* the following code is used for the 'user-friendly' polygonalization
  62.     * routines.  It's not actually compiled in the routines called by Mesa.
  63.     * Mesa passes 3 (or 4) vertices, whereas the 'user-friendly' routines pass
  64.     * all of the parameters as parameters and not vertices.  This setup code
  65.     * fakes the Mesa interface. 
  66.     */
  67.    
  68.    uint v0=0;            /* fake the four vertices passed to the routine */
  69.    uint v1=1;
  70.    uint v2=2;
  71.    uint pv=0;            /* used to selecting color in flat-shaded tris */
  72.    
  73.    struct vertex_buff {      /* create the vertex_buff struct */
  74.      float Win[3][3];
  75.      int   Win2[3][3];
  76.      uint  Color[3][4];
  77.      uint  Index[3];
  78.    };
  79.     
  80.    struct vertex_buff VB;     /* fake the vertex buffer */
  81.  
  82.    /* fill in the 3 vertices in the faked vertex buffer */
  83.    VB.Win2[0][0]=x1<<12;    
  84.    VB.Win2[0][1]=y1<<12;
  85.    VB.Win2[0][2]=((-z2 & 0x7fff) >> 1)<<12;
  86.    VB.Win2[1][0]=x2<<12;
  87.    VB.Win2[1][1]=y2<<12;
  88.    VB.Win2[1][2]=((-z2 & 0x7fff) >> 1)<<12;
  89.    VB.Win2[2][0]=x3<<12;
  90.    VB.Win2[2][1]=y3<<12;
  91.    VB.Win2[2][2]=((-z3 & 0x7fff) >> 1)<<12;
  92.    VB.Color[0][0]=VB.Color[1][0]=VB.Color[2][0]=0xff; /* color=red */ 
  93.    VB.Color[0][1]=VB.Color[0][2]=VB.Color[0][3]=VB.Color[1][1]=VB.Color[1][2]=
  94.    VB.Color[1][3]=
  95.    VB.Color[2][1]=VB.Color[2][2]=VB.Color[2][3]=0;
  96.    VB.Index[0]=VB.Index[1]=VB.Index[2]=2<<12; /* color index=2 */
  97. #else
  98.    
  99.    /* 
  100.     * Mesa uses floating point math! (and it's still fast?!)  Convert floats
  101.     * to fixed point numbers and fixup the z-coords since, the Mondello's
  102.     * z-buffer is a little broken.
  103.     */
  104.  
  105.    /* unrolling ensues */   
  106.    
  107.    /* note: fix Mesa to do this for us.  As it is, many vertices are 
  108.       converted from floats to fixed more than once wasting cycles!
  109.     */
  110.     
  111.    VB.Win2[v0][0]=(uint)VB.Win[v0][0] << 12;
  112.    VB.Win2[v0][1]=(uint)FLIP(VB.Win[v0][1]) << 12;
  113.    VB.Win2[v0][2]=(uint)VB.Win[v0][2] << 12;
  114.    i=(uint)(VB.Win[v0][2]*DEPTH_SCALE);
  115.    VB.Win2[v0][2]=((-i & 0x7fff) >> 1) << 12;
  116.  
  117.    VB.Win2[v1][0]=(uint)VB.Win[v1][0] << 12;
  118.    VB.Win2[v1][1]=(uint)FLIP(VB.Win[v1][1]) << 12;
  119.    VB.Win2[v1][2]=(uint)VB.Win[v1][2] << 12;
  120.    i=(uint)(VB.Win[v1][2]*DEPTH_SCALE);
  121.    VB.Win2[v1][2]=((-i & 0x7fff) >> 1) << 12;
  122.  
  123.    VB.Win2[v2][0]=(uint)VB.Win[v2][0] << 12;
  124.    VB.Win2[v2][1]=(uint)FLIP(VB.Win[v2][1]) << 12;
  125.    VB.Win2[v2][2]=(uint)VB.Win[v2][2] << 12;   
  126.    i=(uint)(VB.Win[v2][2]*DEPTH_SCALE);
  127.    VB.Win2[v2][2]=((-i & 0x7fff) >> 1) << 12;
  128.  
  129. #endif 
  130.  
  131. #ifdef SETUP_CODE
  132.    SETUP_CODE
  133. #endif
  134.  
  135. #ifndef DEBUG_TRITEMP_H
  136.    VB.Win2[v0][1]+=yoffs << 12;
  137.    VB.Win2[v1][1]+=yoffs << 12;
  138.    VB.Win2[v2][1]+=yoffs << 12;
  139. #endif
  140.  
  141. #ifdef DEBUG_TRITEMP_H
  142.    clear24(0,0,0);
  143.    line24_2fc(VB.Win2[v0][0]>>12,0,VB.Win2[v0][0]>>12,400,0xa5,0xa5,0xa5,0);
  144.    line24_2fc(VB.Win2[v1][0]>>12,0,VB.Win2[v1][0]>>12,400,0xa5,0xa5,0xa5,0);
  145.    line24_2fc(VB.Win2[v2][0]>>12,0,VB.Win2[v2][0]>>12,400,0xa5,0xa5,0xa5,0);
  146. /*   line24_2fc(0,VB.Win2[v0][1]>>12,640,VB.Win2[v0][1]>>12,0xa5,0xa5,0xa5,0);
  147.    line24_2fc(0,VB.Win2[v1][1]>>12,640,VB.Win2[v1][1]>>12,0xa5,0xa5,0xa5,0);
  148.    line24_2fc(0,VB.Win2[v2][1]>>12,640,VB.Win2[v2][1]>>12,0xa5,0xa5,0xa5,0);
  149. */
  150. #endif
  151.  
  152.    if( VB.Win2[v0][1] <= VB.Win2[v1][1] ) {
  153.       if( VB.Win2[v0][1] < VB.Win2[v2][1] ) {
  154.          if ( VB.Win2[v1][1] < VB.Win2[v2][1] ) {    /* 0,1,2 */
  155.         min=v0; mid=v1; max=v2;
  156.          }
  157.          else {        /* 0,2,1 */
  158.             min=v0; mid=v2; max=v1;
  159.          }
  160.       }
  161.       else if( VB.Win2[v0][1] == VB.Win2[v2][1] && 
  162.                VB.Win2[v0][1] == VB.Win2[v1][1]) { /* flat line */
  163.          return;
  164.       }
  165.       else {         /* 2,0,1 */
  166.          min=v2; mid=v0; max=v1;
  167.       }
  168.    }
  169.    else {
  170.       if( VB.Win2[v1][1] < VB.Win2[v2][1] ) {
  171.          if ( VB.Win2[v0][1] < VB.Win2[v2][1]) {    /* 1,0,2 */
  172.             min=v1; mid=v0; max=v2;
  173.          }
  174.          else {        /* 1,2,0 */
  175.             min=v1; mid=v2; max=v0;
  176.          }
  177.       }
  178.       else {        /* 2,1,0 */
  179.          min=v2; mid=v1; max=v0;
  180.       } 
  181.    }
  182.  
  183. #ifdef DEBUG_TRITEMP_H
  184.    printf("# (%d,%d)  (%d,%d)  (%d,%d)\n",
  185.           VB.Win2[min][0]>>12,VB.Win2[min][1]>>12,
  186.           VB.Win2[mid][0]>>12,VB.Win2[mid][1]>>12,
  187.           VB.Win2[max][0]>>12,VB.Win2[max][1]>>12);
  188. #endif
  189.  
  190. #ifdef INTERP_COLOR   
  191.    rmin=VB.Color[min][0] >> 3;
  192.    gmin=VB.Color[min][1] >> 3;
  193.    bmin=VB.Color[min][2] >> 3; 
  194.  
  195.    rmid=VB.Color[mid][0] >> 3;
  196.    gmid=VB.Color[mid][1] >> 3;
  197.    bmid=VB.Color[mid][2] >> 3; 
  198.  
  199.    rmax=VB.Color[max][0] >> 3;
  200.    gmax=VB.Color[max][1] >> 3;
  201.    bmax=VB.Color[max][2] >> 3; 
  202. #endif
  203.    
  204.    /* note: Win2[min][0] <= Win2[mid][0] <= Win2[max][0] */
  205.  
  206.    count1=VB.Win2[mid][1]-VB.Win2[min][1];    /* distance btw min and mid */
  207.    count2=VB.Win2[max][1]-VB.Win2[mid][1];       /* distance btw max and mid */
  208.    dy_main=VB.Win2[max][1]-VB.Win2[min][1];      /* distance btw max and min */
  209.  
  210.    dx_main=VB.Win2[max][0]-VB.Win2[min][0];    
  211.    tf=dx_main/(dy_main>>12);            /* dx/dy */
  212.    px=VB.Win2[min][0]+(count1>>6)*(tf>>6);    /* x-intercept on main @ mid */ 
  213.    width=VB.Win2[mid][0]-px;            /* may be neg */
  214.    
  215.    /* note: (count1 >= 0) && (count2 >= 0) && (dy_main >= 0) */
  216.    
  217.    if (dx_main) {
  218.      if (dx_main >= 0)  
  219.        rungmain=(dx_main+0x1000)/((dy_main>>12)+1);
  220.      else
  221.        rungmain=(dx_main-0x1000)/((dy_main>>12)+1);
  222.    }
  223.    else
  224.      rungmain=0;
  225.  
  226.    /* width is always const or increasing from starting point */
  227.    
  228.    t1=VB.Win2[mid][0] - VB.Win2[min][0];
  229.    if (t1 <0) t1=-t1;                /* t1 = abs(t1) */
  230.    rung1=(t1+0x1000)/((count1>>12)+1);             /* rung1 is pos */
  231.  
  232.    /* width may be increasing or decreasing after mid point */
  233.  
  234.    t1=VB.Win2[max][0] - VB.Win2[mid][0];
  235.   
  236.    if (t1 >=0 ) {                    /* maxx >= midx */
  237.      rung2=(t1+0x1000)/((count2>>12)+1);  
  238.    }
  239.    else {                    /* maxx < midx */ 
  240.      rung2=(t1-0x1000)/((count2>>12)+1);
  241.    }
  242.  
  243.    /* note: (rung1 >= 0) && (rung2 may be neg) */
  244.  
  245.    /* fixup the width for a _very_ thin ( < 1 pixel ) line */
  246.  
  247.    t1 = (width<0) ? -width : width;               /* t1 = abs(width)    */
  248.    t2 = (rungmain<0) ? -rungmain : rungmain;    /* t2 = abs(rungmain) */
  249.    
  250.    if (t1<t2)
  251.      width=rungmain;
  252.  
  253.    if (width>0) {
  254.       wopp=width+rung2-rungmain+0x1000;        /* width count+1 scan line */
  255.       if (wopp<t2)
  256.         wopp=t2;
  257.  
  258.       if (rungmain < 0) {
  259.         wbp=rung1-rungmain;            /* width 1st scan line */
  260.         xbp=VB.Win2[min][0]+rungmain;        /* subtract a little */
  261.     span2=wopp+rung2;
  262.       }
  263.       else {
  264.         wbp=rung1;                /* width 1st scan line */
  265.         xbp=VB.Win2[min][0];
  266.         if ( rung2 > 0 )
  267.           span2=wopp-rungmain;
  268.         else
  269.           span2=wopp+rung2-rungmain;
  270.       }
  271. /*      if (wbp<0x1000) {
  272.         wbp+=0x1000;
  273.       } */
  274.       span1=width+0x1800-wbp;
  275.  
  276.    }
  277.    else {                     /* width < 0 */
  278.       wopp=-width-rung2+rungmain+0x1000;    /* width of count+1 line */
  279.       if (wopp<t2)
  280.         wopp=t2;
  281.         
  282.       if (rungmain > 0) {
  283.         wbp=rung1+rungmain;            /* width 1st scan line */
  284.         xbp=VB.Win2[min][0]+rungmain|0x80000000;/* subtract a little */
  285.     span2=wopp-rung2;
  286.       }
  287.       else {
  288.         wbp=rung1;                /* width 1st scan line */
  289.         xbp=VB.Win2[min][0] | 0x80000000;
  290.         if (rung2 < 0)
  291.           span2=wopp+rungmain;
  292.         else
  293.           span2=wopp-rung2+rungmain;
  294.       }
  295.       width=-width;
  296. /*      if (wbp<0x1000)
  297.         wbp+=0x1000; */
  298.       span1=width+0x1000-wbp;
  299.    }     
  300.  
  301.    if (dy_main) {            /* dy_main has no fractional part */
  302.      if (rungmain > 0) 
  303.        dxm=(VB.Win2[max][0]-(xbp & 0x7fffffff))/((dy_main>>12)+1);
  304.      else
  305.        dxm=(VB.Win2[max][0]-(xbp & 0x7fffffff))/((dy_main>>12)+1);
  306.    }
  307.    else
  308.      dxm=0;
  309.  
  310.    if (count1>>12) {
  311.      dw=span1/(count1>>12);
  312.    }
  313.    else
  314.      dw=0;
  315.    
  316.    if (count2>>12) {
  317.      dwopp=span2/-(count2>>12);
  318.    }
  319.    else
  320.      dwopp=0;
  321.              
  322. #ifdef FLAT_INDEX
  323.    *listPtr++ = load_short_ro(BANK_MASK_REG, BLUE_BANK);
  324. #endif
  325. #ifdef INTERP_INDEX
  326.    *listPtr++ = load_short_ro(BANK_MASK_REG, BLUE_BANK);
  327. #endif
  328. #ifdef FLAT_COLOR
  329.    *listPtr++ = load_short_ro(BANK_MASK_REG, RED_BANK);
  330. #endif
  331. #ifdef INTERP_COLOR
  332.    *listPtr++ = load_short_ro(BANK_MASK_REG, RED_BANK);
  333. #endif
  334.  
  335.    *listPtr++ = OPCODE;
  336.    count1 &= 0x00ffff00;
  337.    dy_main=(dy_main>>12)+1;
  338.    count2 &= 0x00ffff00;
  339.    width=(width>>12)+1;
  340.  
  341.    *listPtr++ = ((count1 << 4) & 0xff000000) | VB.Win2[min][1]; /* r1 */
  342.    *listPtr++ = (count1 << 12) | 0x00001000;            /* r2 */
  343.    *listPtr++ = xbp;                         /* r3 */
  344.    *listPtr++ = dxm;                        /* r4 */
  345.    *listPtr++ = VB.Win2[min][2];                /* r5 */
  346.    *listPtr++ = (VB.Win2[max][2]-VB.Win2[min][2])/dy_main; /* r6 */
  347.  #ifdef FLAT_INDEX
  348.    *listPtr++ = VB.Index[pv];                    /* r7 */
  349.    *listPtr++ = 0;                        /* r8 */
  350.  #endif
  351.  #ifdef INTERP_INDEX
  352.    *listPtr++ = VB.Index[mid];                    /* r7 */
  353.    *listPtr++ = (VB.Index[max]-VB.Index[min])/dy_main; /* r8 */
  354.  #endif
  355.  #ifdef FLAT_COLOR
  356.    *listPtr++ = VB.Color[pv][0]<<12;                    /* r7 */
  357.    *listPtr++ = 0;                        /* r8 */
  358.  #endif
  359.  #ifdef INTERP_COLOR
  360.    *listPtr++ = rmin;                        /* r7 */
  361.    *listPtr++ = (rmax-rmin)/dy_main;                     /* r8 */
  362.  #endif
  363.    
  364.    *listPtr++ = wbp;                         /* r9 */
  365.    *listPtr++ = dw;                        /* r10 */
  366.    *listPtr++ = (count2<<4) & 0xff000000 | wopp & 0x00ffffff;    /* r11 */
  367.    *listPtr++ = (count2<<12) | (dwopp & 0x00ffffff);        /* r12 */
  368.    *listPtr++ = 0;                        /* r13 */
  369.    *listPtr++ = (VB.Win2[mid][2]-VB.Win2[min][2])/width;        /* r14 */  
  370.    *listPtr++ = 0;                        /* r15 */
  371.    
  372.    
  373. #ifdef FLAT_INDEX
  374.    *listPtr++ = 0;                        /* r16 */
  375. #endif
  376. #ifdef INTERP_INDEX
  377.    *listPtr++ = 0;                        /* r16 */
  378. #endif
  379.  
  380. #ifdef FLAT_COLOR
  381.    *listPtr++ = 0;                        /* r16 */
  382.  
  383.    /* redraw triangle in green plane */
  384.    *listPtr++ = load_short_ro(BANK_MASK_REG,GREEN_BANK);/* set bank = green */
  385.    *listPtr++ = load_long_ro(IMAIN_REG,1);        /* load imain       */
  386.    *listPtr++ = VB.Color[pv][1]<<12;            /* load green        */ 
  387.    *listPtr++ = OPCODE & ~0x3f;                /* exec, no loads   */
  388.    
  389.    /* redraw triangle in blue plane */
  390.    *listPtr++ = load_short_ro(BANK_MASK_REG,BLUE_BANK);    /* set bank = blue  */
  391.    *listPtr++ = load_long_ro(IMAIN_REG,1);        /* load imain       */
  392.    *listPtr++ = VB.Color[pv][2]<<12;            /* load blue        */
  393.    *listPtr++ = OPCODE2 & ~0x3f;            /* exec, no loads   */
  394. #endif
  395.  
  396. #ifdef INTERP_COLOR
  397.    *listPtr++ = 0;                        /* r16 */
  398.  
  399.    /* redraw triangle in green plane */
  400.    *listPtr++ = load_short_ro(BANK_MASK_REG,GREEN_BANK);/* set bank = green */
  401.    *listPtr++ = load_long_ro(IMAIN_REG,2);        /* load imain, di   */
  402.    *listPtr++ = gmin;                    /* load green       */
  403.    *listPtr++ = (gmax-gmin)/dy_main;            /* load del green   */
  404.    *listPtr++ = load_long_ro(IORTHO_REG,1);        /* load iortho      */
  405.    *listPtr++ = (gmid-gmin)/width;            /* load ortho green */
  406.    *listPtr++ = OPCODE & ~0x3f;                /* exec, no loads   */
  407.    
  408.    /* redraw triangle in blue plane */
  409.    *listPtr++ = load_short_ro(BANK_MASK_REG,BLUE_BANK); /* set bank = blue  */
  410.    *listPtr++ = load_long_ro(IMAIN_REG,2);        /* load imain, di   */
  411.    *listPtr++ = bmin;                   /* load blue        */
  412.    *listPtr++ = (bmax-bmin)/dy_main;            /* load del blue    */
  413.    *listPtr++ = load_long_ro(IORTHO_REG,1);             /* load iortho      */
  414.    *listPtr++ = (bmid-bmin)/width;            /* load ortho blue  */
  415.    *listPtr++ = OPCODE2 & ~0x3f;            /* exec, no loads   */
  416. #endif
  417.   
  418.  
  419.   if ((wopp + dwopp*(count2>>12))<0) {
  420.     printf("** UNDERFLOW **\n");
  421.     exit(-1);
  422.   }
  423.  
  424.   CHKEXECPOLY;
  425.  
  426.   /*
  427.    * check if dpy list full, if is start exec and switch to dpy list 2, 
  428.    * else continue
  429.    */
  430. /*  CHKEXEC; */
  431. }
  432.  
  433. #undef OPCODE
  434. #undef FLAT_INDEX
  435. #undef INTERP_INDEX
  436. #undef FLAT_COLOR
  437. #undef INTERP_COLOR
  438. #undef NOVB
  439.  
  440.