T3DLIB11.CPP
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:286k
源码类别:

游戏

开发平台:

Visual C++

  1.           Draw_Triangle_2DINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  2.           } // end if
  3.        else
  4.           {
  5.           // non alpha version
  6.           Draw_Triangle_2DINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  7.           }  // end if
  8.        } // end if
  9.     else
  10.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  11.        {
  12.         // {andre take advantage of the data structures later..}
  13.         // set the vertices
  14.         face.tvlist[0].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  15.         face.tvlist[0].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  16.         face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  17.         face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  18.         face.tvlist[1].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  19.         face.tvlist[1].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  20.         face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  21.         face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  22.         face.tvlist[2].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  23.         face.tvlist[2].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  24.         face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  25.         face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  26.     // draw the gouraud shaded triangle
  27.         // test for transparency
  28.         if ((rc->attr & RENDER_ATTR_ALPHA) &&
  29.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  30.            {
  31.            // alpha version
  32.            Draw_Gouraud_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  33.            } // end if
  34.         else
  35.            { 
  36.            // non alpha
  37.            Draw_Gouraud_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  38.            } // end if
  39.        } // end if gouraud
  40.     } // end for poly
  41. } // end if RENDER_ATTR_INVZBUFFER
  42. else
  43. if (rc->attr & RENDER_ATTR_WRITETHRUZBUFFER) ////////////////////////////////////
  44. {
  45. // use the write thru z buffer
  46. // we have is a list of polygons and it's time draw them
  47. for (int poly=0; poly < rc->rend_list->num_polys; poly++)
  48.     {
  49.     // render this polygon if and only if it's not clipped, not culled,
  50.     // active, and visible, note however the concecpt of "backface" is 
  51.     // irrelevant in a wire frame engine though
  52.     if (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  53.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  54.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  55.        continue; // move onto next poly
  56.     // test for alpha override
  57.     if (rc->alpha_override>= 0)
  58.        {
  59.        // set alpha to override value
  60.        alpha = rc->alpha_override;
  61.        }  // end if 
  62.     else
  63.         {
  64.         // extract alpha (even if there isn't any)
  65.         alpha = ((rc->rend_list->poly_ptrs[poly]->color & 0xff000000) >> 24);
  66.         } // end else
  67.     // need to test for textured first, since a textured poly can either
  68.     // be emissive, or flat shaded, hence we need to call different
  69.     // rasterizers    
  70.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  71.        {
  72.        // set the vertices
  73.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  74.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  75.        face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  76.        face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
  77.        face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
  78.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  79.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  80.        face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  81.        face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
  82.        face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
  83.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  84.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  85.        face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  86.        face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
  87.        face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
  88.     
  89.        // test if this is a mipmapped polygon?
  90.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
  91.           {
  92.           // determine if mipmapping is desired at all globally
  93.           if (rc->attr & RENDER_ATTR_MIPMAP)
  94.              {
  95.              // determine mip level for this polygon
  96.              // first determine how many miplevels there are in mipchain for this polygon
  97.              int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
  98.              // now based on the requested linear miplevel fall off distance, cut
  99.              // the viewdistance into segments, determine what segment polygon is
  100.              // in and select mip level -- simple! later you might want something more
  101.              // robust, also note I only use a single vertex, you might want to find the average
  102.              // since for long walls perpendicular to view direction this might causing mip
  103.              // popping mid surface
  104.              int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
  105.           
  106.              // clamp miplevel
  107.              if (miplevel > tmiplevels) miplevel = tmiplevels;
  108.              // based on miplevel select proper texture
  109.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
  110.              // now we must divide each texture coordinate by 2 per miplevel
  111.              for (int ts = 0; ts < miplevel; ts++)
  112.                  {
  113.                  face.tvlist[0].u0*=.5;
  114.                  face.tvlist[0].v0*=.5;
  115.                  face.tvlist[1].u0*=.5;
  116.                  face.tvlist[1].v0*=.5;
  117.                  face.tvlist[2].u0*=.5;
  118.                  face.tvlist[2].v0*=.5;
  119.                 } // end for
  120.              } // end if mipmmaping enabled globally
  121.           else // mipmapping not selected globally
  122.              {
  123.              // in this case the polygon IS mipmapped, but the caller has requested NO
  124.              // mipmapping, so we will support this by selecting mip level 0 since the
  125.              // texture pointer is pointing to a mip chain regardless
  126.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
  127.  
  128.              // note: texture coordinate manipulation is unneeded
  129.              } // end else
  130.           } // end if
  131.        else
  132.           {
  133.           // assign the texture without change
  134.           face.texture = rc->rend_list->poly_ptrs[poly]->texture;
  135.           } // end if
  136.        
  137.        // is this a plain emissive texture?
  138.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  139.           {
  140.           // draw the textured triangle as emissive
  141.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  142.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  143.              {
  144.              // alpha version
  145.              
  146.              // which texture mapper?
  147.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  148.                 {
  149.                 Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  150.                 } // end if
  151.              else
  152.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  153.                 {
  154.                 // not supported yet!
  155.                 Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  156.                 } // end if
  157.              else
  158.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  159.                 {
  160.                 // not supported yet
  161.                 Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  162.                 } // end if
  163.              else
  164.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  165.                 {
  166.                 // test z distance again perspective transition gate
  167.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  168.                     {
  169.                     // default back to affine
  170.                     Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  171.                     } // end if
  172.                 else
  173.                     {
  174.                     // use perspective linear
  175.                     // not supported yet
  176.                     Draw_Textured_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  177.                     } // end if
  178.                  } // end if
  179.              } // end if
  180.           else
  181.              {
  182.              // non alpha
  183.              // which texture mapper?
  184.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  185.                 {
  186.                 // use bilerp?
  187.                 if (rc->attr & RENDER_ATTR_BILERP)
  188.                    Draw_Textured_Bilerp_TriangleZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);               
  189.                 else
  190.                    Draw_Textured_TriangleWTZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  191.                 } // end if
  192.              else
  193.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  194.                 {
  195.                 // not supported yet
  196.                 Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  197.                 } // end if
  198.              else
  199.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  200.                 {
  201.                 // not supported yet
  202.                 Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  203.                 } // end if
  204.              else
  205.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  206.                 {
  207.                 // test z distance again perspective transition gate
  208.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  209.                     {
  210.                     // default back to affine
  211.                     Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  212.                     } // end if
  213.                 else
  214.                     {
  215.                     // use perspective linear
  216.                     // not supported yet
  217.                     Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  218.                     } // end if
  219.                 } // end if
  220.              } // end if
  221.           } // end if
  222.        else
  223.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
  224.           {
  225.           // draw as flat shaded
  226.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  227.           // test for transparency
  228.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  229.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  230.              {
  231.              // alpha version
  232.              // which texture mapper?
  233.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  234.                 {
  235.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  236.                 } // end if
  237.              else
  238.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  239.                 {
  240.                 // not supported yet
  241.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  242.                 } // end if
  243.              else
  244.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  245.                 {
  246.                 // not supported yet
  247.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  248.                 } // end if
  249.              else
  250.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  251.                 {
  252.                 // test z distance again perspective transition gate
  253.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  254.                     {
  255.                     // default back to affine
  256.                     Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  257.                     } // end if
  258.                 else
  259.                     {
  260.                     // use perspective linear
  261.                     // not supported yet
  262.                     Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  263.                     } // end if
  264.                  } // end if
  265.              } // end if
  266.           else
  267.              {
  268.              // non alpha
  269.              // which texture mapper?
  270.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  271.                 {
  272.                 Draw_Textured_TriangleFSWTZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  273.                 } // end if
  274.              else
  275.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  276.                 {
  277.                 // not supported yet
  278.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  279.                 } // end if
  280.              else
  281.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  282.                 {
  283.                 // not supported yet
  284.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  285.                 } // end if
  286.              else
  287.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  288.                 {
  289.                 // test z distance again perspective transition gate
  290.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  291.                     {
  292.                     // default back to affine
  293.                     Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  294.                     } // end if
  295.                 else
  296.                     {
  297.                     // use perspective linear
  298.                     // not supported yet
  299.                     Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  300.                     } // end if
  301.                  } // end if
  302.              } // end if
  303.           } // end else if
  304.       else
  305.          { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  306.           // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  307.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  308.           face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  309.           face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  310.          // test for transparency
  311.          if ((rc->attr & RENDER_ATTR_ALPHA) &&
  312.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  313.              {
  314.              // alpha version
  315.              // which texture mapper?
  316.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  317.                 {
  318.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  319.                 } // end if
  320.              else
  321.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  322.                 {
  323.                 // not supported yet :)
  324.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  325.                 } // end if
  326.              else
  327.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  328.                 {
  329.                 // not supported yet :)
  330.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  331.                 } // end if
  332.              else
  333.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  334.                 {
  335.                 // test z distance again perspective transition gate
  336.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  337.                     {
  338.                     // default back to affine
  339.                     Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  340.                     } // end if
  341.                 else
  342.                     {
  343.                     // use perspective linear
  344.                     // not supported yet :)
  345.                     Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  346.                     } // end if
  347.                  } // end if
  348.              } // end if
  349.           else
  350.              {
  351.              // non alpha
  352.              // which texture mapper?
  353.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  354.                 {
  355.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  356.                 } // end if
  357.              else
  358.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  359.                 {
  360.                 // not supported yet :)
  361.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  362.                 } // end if
  363.              else
  364.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  365.                 {
  366.                 // not supported yet :)
  367.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  368.                 } // end if
  369.              else
  370.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  371.                 {
  372.                 // test z distance again perspective transition gate
  373.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  374.                     {
  375.                     // default back to affine
  376.                     Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  377.                     } // end if
  378.                 else
  379.                     {
  380.                     // use perspective linear
  381.                     // not supported yet :)
  382.                     Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  383.                     } // end if
  384.                  } // end if
  385.              } // end if
  386.          } // end else
  387.        } // end if      
  388.     else
  389.     if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  390.         (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  391.        {
  392.        // draw as constant shaded
  393.        face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  394.        
  395.        // set the vertices
  396.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  397.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  398.        face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  399.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  400.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  401.        face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  402.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  403.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  404.        face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  405.        // draw the triangle with basic flat rasterizer
  406.        // test for transparency
  407.        if ((rc->attr & RENDER_ATTR_ALPHA) &&
  408.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  409.           {
  410.           // alpha version
  411.           Draw_Triangle_2DZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  412.           } // end if
  413.        else
  414.           {
  415.           // non alpha version
  416.           Draw_Triangle_2DZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  417.           }  // end if
  418.        } // end if
  419.     else
  420.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  421.        {
  422.         // {andre take advantage of the data structures later..}
  423.         // set the vertices
  424.         face.tvlist[0].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  425.         face.tvlist[0].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  426.         face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  427.         face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  428.         face.tvlist[1].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  429.         face.tvlist[1].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  430.         face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  431.         face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  432.         face.tvlist[2].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  433.         face.tvlist[2].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  434.         face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  435.         face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  436.     // draw the gouraud shaded triangle
  437.         // test for transparency
  438.         if ((rc->attr & RENDER_ATTR_ALPHA) &&
  439.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  440.            {
  441.            // alpha version
  442.            Draw_Gouraud_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  443.            } // end if
  444.         else
  445.            { 
  446.            // non alpha
  447.            Draw_Gouraud_TriangleWTZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  448.            } // end if
  449.        } // end if gouraud
  450.     } // end for poly
  451. } // end if RENDER_ATTR_ZBUFFER
  452. } // end Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_2
  453. ////////////////////////////////////////////////////////////////////////////////////////
  454. void Draw_Textured_TriangleWTZB2_16(POLYF4DV2_PTR face,  // ptr to face
  455.                               UCHAR *_dest_buffer,       // pointer to video buffer
  456.                               int mem_pitch,             // bytes per line, 320, 640 etc.
  457.                               UCHAR *_zbuffer,           // pointer to z-buffer
  458.                               int zpitch)                // bytes per line of zbuffer
  459. {
  460. // this function draws a textured triangle in 16-bit mode
  461. int v0=0,
  462.     v1=1,
  463. v2=2,
  464. temp=0,
  465. tri_type = TRI_TYPE_NONE,
  466. irestart = INTERP_LHS;
  467. int dx,dy,dyl,dyr,      // general deltas
  468.     u,v,z,
  469.     du,dv,dz,
  470.     xi,yi,              // the current interpolated x,y
  471. ui,vi,zi,           // the current interpolated u,v,z
  472. index_x,index_y,    // looping vars
  473. x,y,                // hold general x,y
  474. xstart,
  475. xend,
  476. ystart,
  477. yrestart,
  478. yend,
  479. xl,                 
  480. dxdyl,              
  481. xr,
  482. dxdyr,             
  483. dudyl,    
  484. ul,
  485. dvdyl,   
  486. vl,
  487. dzdyl,   
  488. zl,
  489. dudyr,
  490. ur,
  491. dvdyr,
  492. vr,
  493. dzdyr,
  494. zr;
  495. int x0,y0,tu0,tv0,tz0,    // cached vertices
  496. x1,y1,tu1,tv1,tz1,
  497. x2,y2,tu2,tv2,tz2;
  498. USHORT *screen_ptr  = NULL,
  499.    *screen_line = NULL,
  500.    *textmap     = NULL,
  501.        *dest_buffer = (USHORT *)_dest_buffer;                       
  502. UINT  *z_ptr = NULL,
  503.       *zbuffer = (UINT *)_zbuffer;
  504. #ifdef DEBUG_ON
  505. // track rendering stats
  506.     debug_polys_rendered_per_frame++;
  507. #endif
  508. // extract texture map
  509. textmap = (USHORT *)face->texture->buffer;
  510. // extract base 2 of texture width
  511. int texture_shift2 = logbase2ofx[face->texture->width];
  512. // adjust memory pitch to words, divide by 2
  513. mem_pitch >>=1;
  514. // adjust zbuffer pitch for 32 bit alignment
  515. zpitch >>= 2;
  516. // apply fill convention to coordinates
  517. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  518. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  519. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  520. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  521. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  522. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  523. // first trivial clipping rejection tests 
  524. if (((face->tvlist[0].y < min_clip_y)  && 
  525.  (face->tvlist[1].y < min_clip_y)  &&
  526.  (face->tvlist[2].y < min_clip_y)) ||
  527. ((face->tvlist[0].y > max_clip_y)  && 
  528.  (face->tvlist[1].y > max_clip_y)  &&
  529.  (face->tvlist[2].y > max_clip_y)) ||
  530. ((face->tvlist[0].x < min_clip_x)  && 
  531.  (face->tvlist[1].x < min_clip_x)  &&
  532.  (face->tvlist[2].x < min_clip_x)) ||
  533. ((face->tvlist[0].x > max_clip_x)  && 
  534.  (face->tvlist[1].x > max_clip_x)  &&
  535.  (face->tvlist[2].x > max_clip_x)))
  536.    return;
  537. // sort vertices
  538. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  539. {SWAP(v0,v1,temp);} 
  540. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  541. {SWAP(v0,v2,temp);}
  542. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  543. {SWAP(v1,v2,temp);}
  544. // now test for trivial flat sided cases
  545. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  546. // set triangle type
  547. tri_type = TRI_TYPE_FLAT_TOP;
  548. // sort vertices left to right
  549. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  550. {SWAP(v0,v1,temp);}
  551. } // end if
  552. else
  553. // now test for trivial flat sided cases
  554. if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
  555. // set triangle type
  556. tri_type = TRI_TYPE_FLAT_BOTTOM;
  557. // sort vertices left to right
  558. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  559. {SWAP(v1,v2,temp);}
  560. } // end if
  561. else
  562. {
  563. // must be a general triangle
  564. tri_type = TRI_TYPE_GENERAL;
  565. } // end else
  566. // extract vertices for processing, now that we have order
  567. x0  = (int)(face->tvlist[v0].x+0.0);
  568. y0  = (int)(face->tvlist[v0].y+0.0);
  569. tu0 = (int)(face->tvlist[v0].u0);
  570. tv0 = (int)(face->tvlist[v0].v0);
  571. tz0 = (int)(face->tvlist[v0].z+0.5);
  572. x1  = (int)(face->tvlist[v1].x+0.0);
  573. y1  = (int)(face->tvlist[v1].y+0.0);
  574. tu1 = (int)(face->tvlist[v1].u0);
  575. tv1 = (int)(face->tvlist[v1].v0);
  576. tz1 = (int)(face->tvlist[v1].z+0.5);
  577. x2  = (int)(face->tvlist[v2].x+0.0);
  578. y2  = (int)(face->tvlist[v2].y+0.0);
  579. tu2 = (int)(face->tvlist[v2].u0);
  580. tv2 = (int)(face->tvlist[v2].v0);
  581. tz2 = (int)(face->tvlist[v2].z+0.5);
  582. // degenerate triangle
  583. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  584.    return;
  585. // set interpolation restart value
  586. yrestart = y1;
  587. // what kind of triangle
  588. if (tri_type & TRI_TYPE_FLAT_MASK)
  589. {
  590. if (tri_type == TRI_TYPE_FLAT_TOP)
  591. {
  592. // compute all deltas
  593. dy = (y2 - y0);
  594. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  595. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  596. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  597. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  598. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  599. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  600. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  601. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;  
  602. // test for y clipping
  603. if (y0 < min_clip_y)
  604. {
  605. // compute overclip
  606. dy = (min_clip_y - y0);
  607. // computer new LHS starting values
  608. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  609. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  610. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  611. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  612. // compute new RHS starting values
  613. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  614. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  615. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  616. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  617. // compute new starting y
  618. ystart = min_clip_y;
  619. } // end if
  620. else
  621. {
  622. // no clipping
  623. // set starting values
  624. xl = (x0 << FIXP16_SHIFT);
  625. xr = (x1 << FIXP16_SHIFT);
  626. ul = (tu0 << FIXP16_SHIFT);
  627. vl = (tv0 << FIXP16_SHIFT);
  628. zl = (tz0 << FIXP16_SHIFT);
  629. ur = (tu1 << FIXP16_SHIFT);
  630. vr = (tv1 << FIXP16_SHIFT);
  631. zr = (tz1 << FIXP16_SHIFT);
  632. // set starting y
  633. ystart = y0;
  634. } // end else
  635. } // end if flat top
  636. else
  637. {
  638. // must be flat bottom
  639. // compute all deltas
  640. dy = (y1 - y0);
  641. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  642. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  643. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  644. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;   
  645. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  646. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  647. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  648. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  649. // test for y clipping
  650. if (y0 < min_clip_y)
  651. {
  652. // compute overclip
  653. dy = (min_clip_y - y0);
  654. // computer new LHS starting values
  655. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  656. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  657. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  658. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  659. // compute new RHS starting values
  660. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  661. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  662. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  663. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  664. // compute new starting y
  665. ystart = min_clip_y;
  666. } // end if
  667. else
  668. {
  669. // no clipping
  670. // set starting values
  671. xl = (x0 << FIXP16_SHIFT);
  672. xr = (x0 << FIXP16_SHIFT);
  673. ul = (tu0 << FIXP16_SHIFT);
  674. vl = (tv0 << FIXP16_SHIFT);
  675. zl = (tz0 << FIXP16_SHIFT);
  676. ur = (tu0 << FIXP16_SHIFT);
  677. vr = (tv0 << FIXP16_SHIFT);
  678. zr = (tz0 << FIXP16_SHIFT);
  679. // set starting y
  680. ystart = y0;
  681. } // end else
  682. } // end else flat bottom
  683. // test for bottom clip, always
  684. if ((yend = y2) > max_clip_y)
  685. yend = max_clip_y;
  686.     // test for horizontal clipping
  687. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  688. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  689. (x2 < min_clip_x) || (x2 > max_clip_x))
  690. {
  691.     // clip version
  692. // point screen ptr to starting line
  693. screen_ptr = dest_buffer + (ystart * mem_pitch);
  694.     // point zbuffer to starting line
  695.     z_ptr = zbuffer + (ystart * zpitch);
  696. for (yi = ystart; yi < yend; yi++)
  697. {
  698. // compute span endpoints
  699. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  700. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  701. // compute starting points for u,v interpolants
  702. ui = ul + FIXP16_ROUND_UP;
  703. vi = vl + FIXP16_ROUND_UP;
  704. zi = zl + FIXP16_ROUND_UP;
  705. // compute u,v interpolants
  706. if ((dx = (xend - xstart))>0)
  707. {
  708. du = (ur - ul)/dx;
  709. dv = (vr - vl)/dx;
  710. dz = (zr - zl)/dx;
  711. } // end if
  712. else
  713. {
  714. du = (ur - ul);
  715. dv = (vr - vl);
  716. dz = (zr - zl);
  717. } // end else
  718. ///////////////////////////////////////////////////////////////////////
  719. // test for x clipping, LHS
  720. if (xstart < min_clip_x)
  721. {
  722. // compute x overlap
  723. dx = min_clip_x - xstart;
  724. // slide interpolants over
  725. ui+=dx*du;
  726. vi+=dx*dv;
  727. zi+=dx*dz;
  728. // reset vars
  729. xstart = min_clip_x;
  730. } // end if
  731. // test for x clipping RHS
  732. if (xend > max_clip_x)
  733. xend = max_clip_x;
  734. ///////////////////////////////////////////////////////////////////////
  735. // draw span
  736. for (xi=xstart; xi < xend; xi++)
  737. {
  738.             // write thru the z buffer always
  739.     // write textel
  740.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  741.             // update z-buffer
  742.             z_ptr[xi] = zi;           
  743. // interpolate u,v,z
  744. ui+=du;
  745. vi+=dv;
  746. zi+=dz;
  747. } // end for xi
  748. // interpolate u,v,x along right and left edge
  749. xl+=dxdyl;
  750. ul+=dudyl;
  751. vl+=dvdyl;
  752. zl+=dzdyl;
  753. xr+=dxdyr;
  754. ur+=dudyr;
  755. vr+=dvdyr;
  756. zr+=dzdyr;
  757.  
  758. // advance screen ptr
  759. screen_ptr+=mem_pitch;
  760.         // advance zbuffer ptr
  761.         z_ptr+=zpitch;
  762. } // end for y
  763. } // end if clip
  764. else
  765. {
  766. // non-clip version
  767. // point screen ptr to starting line
  768. screen_ptr = dest_buffer + (ystart * mem_pitch);
  769.     // point zbuffer to starting line
  770.     z_ptr = zbuffer + (ystart * zpitch);
  771. for (yi = ystart; yi < yend; yi++)
  772. {
  773. // compute span endpoints
  774. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  775. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  776. // compute starting points for u,v interpolants
  777. ui = ul + FIXP16_ROUND_UP;
  778. vi = vl + FIXP16_ROUND_UP;
  779. zi = zl + FIXP16_ROUND_UP;
  780. // compute u,v interpolants
  781. if ((dx = (xend - xstart))>0)
  782. {
  783. du = (ur - ul)/dx;
  784. dv = (vr - vl)/dx;
  785. dz = (zr - zl)/dx;
  786. } // end if
  787. else
  788. {
  789. du = (ur - ul);
  790. dv = (vr - vl);
  791. dz = (zr - zl);
  792. } // end else
  793. // draw span
  794. for (xi=xstart; xi < xend; xi++)
  795. {
  796.             // write thru the z buffer always
  797.     // write textel
  798.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  799.             // update z-buffer
  800.             z_ptr[xi] = zi;   
  801. // interpolate u,v,z
  802. ui+=du;
  803. vi+=dv;
  804. zi+=dz;
  805. } // end for xi
  806. // interpolate u,v,x along right and left edge
  807. xl+=dxdyl;
  808. ul+=dudyl;
  809. vl+=dvdyl;
  810. zl+=dzdyl;
  811. xr+=dxdyr;
  812. ur+=dudyr;
  813. vr+=dvdyr;
  814. zr+=dzdyr;
  815. // advance screen ptr
  816. screen_ptr+=mem_pitch;
  817.         // advance zbuffer ptr
  818.         z_ptr+=zpitch;
  819. } // end for y
  820. } // end if non-clipped
  821. } // end if
  822. else
  823. if (tri_type==TRI_TYPE_GENERAL)
  824. {
  825. // first test for bottom clip, always
  826. if ((yend = y2) > max_clip_y)
  827. yend = max_clip_y;
  828. // pre-test y clipping status
  829. if (y1 < min_clip_y)
  830. {
  831. // compute all deltas
  832. // LHS
  833. dyl = (y2 - y1);
  834. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  835. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  836. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  837. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  838. // RHS
  839. dyr = (y2 - y0);
  840. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  841. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  842. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  843. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  844. // compute overclip
  845. dyr = (min_clip_y - y0);
  846. dyl = (min_clip_y - y1);
  847. // computer new LHS starting values
  848. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  849. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  850. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  851. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  852. // compute new RHS starting values
  853. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  854. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  855. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  856. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  857. // compute new starting y
  858. ystart = min_clip_y;
  859. // test if we need swap to keep rendering left to right
  860. if (dxdyr > dxdyl)
  861. {
  862. SWAP(dxdyl,dxdyr,temp);
  863. SWAP(dudyl,dudyr,temp);
  864. SWAP(dvdyl,dvdyr,temp);
  865. SWAP(dzdyl,dzdyr,temp);
  866. SWAP(xl,xr,temp);
  867. SWAP(ul,ur,temp);
  868. SWAP(vl,vr,temp);
  869. SWAP(zl,zr,temp);
  870. SWAP(x1,x2,temp);
  871. SWAP(y1,y2,temp);
  872. SWAP(tu1,tu2,temp);
  873. SWAP(tv1,tv2,temp);
  874. SWAP(tz1,tz2,temp);
  875. // set interpolation restart
  876. irestart = INTERP_RHS;
  877. } // end if
  878. } // end if
  879. else
  880. if (y0 < min_clip_y)
  881. {
  882. // compute all deltas
  883. // LHS
  884. dyl = (y1 - y0);
  885. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  886. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  887. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  888. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  889. // RHS
  890. dyr = (y2 - y0);
  891. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  892. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  893. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  894. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  895. // compute overclip
  896. dy = (min_clip_y - y0);
  897. // computer new LHS starting values
  898. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  899. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  900. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  901. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  902. // compute new RHS starting values
  903. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  904. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  905. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  906. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  907. // compute new starting y
  908. ystart = min_clip_y;
  909. // test if we need swap to keep rendering left to right
  910. if (dxdyr < dxdyl)
  911. {
  912. SWAP(dxdyl,dxdyr,temp);
  913. SWAP(dudyl,dudyr,temp);
  914. SWAP(dvdyl,dvdyr,temp);
  915. SWAP(dzdyl,dzdyr,temp);
  916. SWAP(xl,xr,temp);
  917. SWAP(ul,ur,temp);
  918. SWAP(vl,vr,temp);
  919. SWAP(zl,zr,temp);
  920. SWAP(x1,x2,temp);
  921. SWAP(y1,y2,temp);
  922. SWAP(tu1,tu2,temp);
  923. SWAP(tv1,tv2,temp);
  924. SWAP(tz1,tz2,temp);
  925. // set interpolation restart
  926. irestart = INTERP_RHS;
  927. } // end if
  928. } // end if
  929. else
  930. {
  931. // no initial y clipping
  932. // compute all deltas
  933. // LHS
  934. dyl = (y1 - y0);
  935. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  936. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  937. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  938. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;   
  939. // RHS
  940. dyr = (y2 - y0);
  941. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  942. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  943. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  944. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  945. // no clipping y
  946. // set starting values
  947. xl = (x0 << FIXP16_SHIFT);
  948. xr = (x0 << FIXP16_SHIFT);
  949. ul = (tu0 << FIXP16_SHIFT);
  950. vl = (tv0 << FIXP16_SHIFT);
  951. zl = (tz0 << FIXP16_SHIFT);
  952. ur = (tu0 << FIXP16_SHIFT);
  953. vr = (tv0 << FIXP16_SHIFT);
  954. zr = (tz0 << FIXP16_SHIFT);
  955. // set starting y
  956. ystart = y0;
  957. // test if we need swap to keep rendering left to right
  958. if (dxdyr < dxdyl)
  959. {
  960. SWAP(dxdyl,dxdyr,temp);
  961. SWAP(dudyl,dudyr,temp);
  962. SWAP(dvdyl,dvdyr,temp);
  963. SWAP(dzdyl,dzdyr,temp);
  964. SWAP(xl,xr,temp);
  965. SWAP(ul,ur,temp);
  966. SWAP(vl,vr,temp);
  967. SWAP(zl,zr,temp);
  968. SWAP(x1,x2,temp);
  969. SWAP(y1,y2,temp);
  970. SWAP(tu1,tu2,temp);
  971. SWAP(tv1,tv2,temp);
  972. SWAP(tz1,tz2,temp);
  973. // set interpolation restart
  974. irestart = INTERP_RHS;
  975. } // end if
  976. } // end else
  977.     // test for horizontal clipping
  978. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  979. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  980. (x2 < min_clip_x) || (x2 > max_clip_x))
  981. {
  982.     // clip version
  983. // x clipping
  984. // point screen ptr to starting line
  985. screen_ptr = dest_buffer + (ystart * mem_pitch);
  986.     // point zbuffer to starting line
  987.     z_ptr = zbuffer + (ystart * zpitch);
  988. for (yi = ystart; yi < yend; yi++)
  989. {
  990. // compute span endpoints
  991. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  992. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  993. // compute starting points for u,v interpolants
  994. ui = ul + FIXP16_ROUND_UP;
  995. vi = vl + FIXP16_ROUND_UP;
  996. zi = zl + FIXP16_ROUND_UP;
  997. // compute u,v interpolants
  998. if ((dx = (xend - xstart))>0)
  999. {
  1000. du = (ur - ul)/dx;
  1001. dv = (vr - vl)/dx;
  1002. dz = (zr - zl)/dx;
  1003. } // end if
  1004. else
  1005. {
  1006. du = (ur - ul);
  1007. dv = (vr - vl);
  1008. dz = (zr - zl);
  1009. } // end else
  1010. ///////////////////////////////////////////////////////////////////////
  1011. // test for x clipping, LHS
  1012. if (xstart < min_clip_x)
  1013. {
  1014. // compute x overlap
  1015. dx = min_clip_x - xstart;
  1016. // slide interpolants over
  1017. ui+=dx*du;
  1018. vi+=dx*dv;
  1019. zi+=dx*dz;
  1020. // set x to left clip edge
  1021. xstart = min_clip_x;
  1022. } // end if
  1023. // test for x clipping RHS
  1024. if (xend > max_clip_x)
  1025. xend = max_clip_x;
  1026. ///////////////////////////////////////////////////////////////////////
  1027. // draw span
  1028. for (xi=xstart; xi < xend; xi++)
  1029. {
  1030.             // write thru the z buffer always
  1031.     // write textel
  1032.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1033.             // update z-buffer
  1034.             z_ptr[xi] = zi;   
  1035. // interpolate u,v,z
  1036. ui+=du;
  1037. vi+=dv;
  1038. zi+=dz;
  1039. } // end for xi
  1040. // interpolate u,v,x along right and left edge
  1041. xl+=dxdyl;
  1042. ul+=dudyl;
  1043. vl+=dvdyl;
  1044. zl+=dzdyl;
  1045. xr+=dxdyr;
  1046. ur+=dudyr;
  1047. vr+=dvdyr;
  1048. zr+=dzdyr;
  1049. // advance screen ptr
  1050. screen_ptr+=mem_pitch;
  1051.         // advance zbuffer ptr
  1052.         z_ptr+=zpitch;
  1053. // test for yi hitting second region, if so change interpolant
  1054. if (yi==yrestart)
  1055. {
  1056.     // test interpolation side change flag
  1057. if (irestart == INTERP_LHS)
  1058. {
  1059. // LHS
  1060. dyl = (y2 - y1);
  1061. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1062. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1063. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1064. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  1065. // set starting values
  1066. xl = (x1  << FIXP16_SHIFT);
  1067. ul = (tu1 << FIXP16_SHIFT);
  1068. vl = (tv1 << FIXP16_SHIFT);
  1069. zl = (tz1 << FIXP16_SHIFT);
  1070. // interpolate down on LHS to even up
  1071. xl+=dxdyl;
  1072. ul+=dudyl;
  1073. vl+=dvdyl;
  1074. zl+=dzdyl;
  1075. } // end if
  1076. else
  1077. {
  1078. // RHS
  1079. dyr = (y1 - y2);
  1080. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1081. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1082. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1083. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;  
  1084. // set starting values
  1085. xr = (x2  << FIXP16_SHIFT);
  1086. ur = (tu2 << FIXP16_SHIFT);
  1087. vr = (tv2 << FIXP16_SHIFT);
  1088. zr = (tz2 << FIXP16_SHIFT);
  1089. // interpolate down on RHS to even up
  1090. xr+=dxdyr;
  1091. ur+=dudyr;
  1092. vr+=dvdyr;
  1093. zr+=dzdyr;
  1094. } // end else
  1095. } // end if
  1096. } // end for y
  1097. } // end if
  1098. else
  1099. {
  1100. // no x clipping
  1101. // point screen ptr to starting line
  1102. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1103.     // point zbuffer to starting line
  1104.     z_ptr = zbuffer + (ystart * zpitch);
  1105. for (yi = ystart; yi < yend; yi++)
  1106. {
  1107. // compute span endpoints
  1108. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1109. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1110. // compute starting points for u,v interpolants
  1111. ui = ul + FIXP16_ROUND_UP;
  1112. vi = vl + FIXP16_ROUND_UP;
  1113. zi = zl + FIXP16_ROUND_UP;
  1114. // compute u,v interpolants
  1115. if ((dx = (xend - xstart))>0)
  1116. {
  1117. du = (ur - ul)/dx;
  1118. dv = (vr - vl)/dx;
  1119. dz = (zr - zl)/dx;
  1120. } // end if
  1121. else
  1122. {
  1123. du = (ur - ul);
  1124. dv = (vr - vl);
  1125. dz = (zr - zl);
  1126. } // end else
  1127. // draw span
  1128. for (xi=xstart; xi < xend; xi++)
  1129. {
  1130.             // write thru the z buffer always
  1131.     // write textel
  1132.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1133.             // update z-buffer
  1134.             z_ptr[xi] = zi;   
  1135. // interpolate u,v
  1136. ui+=du;
  1137. vi+=dv;
  1138. zi+=dz;
  1139. } // end for xi
  1140. // interpolate u,v,x along right and left edge
  1141. xl+=dxdyl;
  1142. ul+=dudyl;
  1143. vl+=dvdyl;
  1144. zl+=dzdyl;
  1145. xr+=dxdyr;
  1146. ur+=dudyr;
  1147. vr+=dvdyr;
  1148. zr+=dzdyr;
  1149. // advance screen ptr
  1150. screen_ptr+=mem_pitch;
  1151.         // advance zbuffer ptr
  1152.         z_ptr+=zpitch;
  1153. // test for yi hitting second region, if so change interpolant
  1154. if (yi==yrestart)
  1155. {
  1156. // test interpolation side change flag
  1157. if (irestart == INTERP_LHS)
  1158. {
  1159. // LHS
  1160. dyl = (y2 - y1);
  1161. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1162. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1163. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1164. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  1165. // set starting values
  1166. xl = (x1  << FIXP16_SHIFT);
  1167. ul = (tu1 << FIXP16_SHIFT);
  1168. vl = (tv1 << FIXP16_SHIFT);
  1169. zl = (tz1 << FIXP16_SHIFT);
  1170. // interpolate down on LHS to even up
  1171. xl+=dxdyl;
  1172. ul+=dudyl;
  1173. vl+=dvdyl;
  1174. zl+=dzdyl;
  1175. } // end if
  1176. else
  1177. {
  1178. // RHS
  1179. dyr = (y1 - y2);
  1180. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1181. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1182. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1183. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr; 
  1184. // set starting values
  1185. xr = (x2  << FIXP16_SHIFT);
  1186. ur = (tu2 << FIXP16_SHIFT);
  1187. vr = (tv2 << FIXP16_SHIFT);
  1188. zr = (tz2 << FIXP16_SHIFT);
  1189. // interpolate down on RHS to even up
  1190. xr+=dxdyr;
  1191. ur+=dudyr;
  1192. vr+=dvdyr;
  1193. zr+=dzdyr;
  1194. } // end else
  1195. } // end if
  1196. } // end for y
  1197.    } // end else
  1198. } // end if
  1199. } // end Draw_Textured_TriangleWTZB2_16
  1200. ///////////////////////////////////////////////////////////////////////////////
  1201. ///////////////////////////////////////////////////////////////////////////////
  1202. void Draw_Textured_TriangleFSWTZB2_16(POLYF4DV2_PTR face, // ptr to face
  1203.                                  UCHAR *_dest_buffer,  // pointer to video buffer
  1204.                                  int mem_pitch,        // bytes per line, 320, 640 etc.
  1205.                                  UCHAR *_zbuffer,       // pointer to z-buffer
  1206.                                  int zpitch)          // bytes per line of zbuffer
  1207. {
  1208. // this function draws a textured triangle in 16-bit mode with flat shading
  1209. int v0=0,
  1210.     v1=1,
  1211. v2=2,
  1212. temp=0,
  1213. tri_type = TRI_TYPE_NONE,
  1214. irestart = INTERP_LHS;
  1215. int dx,dy,dyl,dyr,      // general deltas
  1216.     u,v,z,
  1217.     du,dv,dz,
  1218.     xi,yi,              // the current interpolated x,y
  1219. ui,vi,zi,            // the current interpolated u,v,z
  1220. index_x,index_y,    // looping vars
  1221. x,y,                // hold general x,y
  1222. xstart,
  1223. xend,
  1224. ystart,
  1225. yrestart,
  1226. yend,
  1227. xl,                 
  1228. dxdyl,              
  1229. xr,
  1230. dxdyr,             
  1231. dudyl,    
  1232. ul,
  1233. dzdyl,    
  1234. zl,
  1235. dvdyl,   
  1236. vl,
  1237. dudyr,
  1238. ur,
  1239. dvdyr,
  1240. vr,
  1241. dzdyr,
  1242. zr;
  1243. USHORT r_base, g_base, b_base,
  1244.        r_textel, g_textel, b_textel, textel;
  1245. int x0,y0,tu0,tv0,tz0,    // cached vertices
  1246. x1,y1,tu1,tv1,tz1,
  1247. x2,y2,tu2,tv2,tz2;
  1248. USHORT *screen_ptr  = NULL,
  1249.    *screen_line = NULL,
  1250.    *textmap     = NULL,
  1251.        *dest_buffer = (USHORT *)_dest_buffer;
  1252. UINT  *z_ptr = NULL,
  1253.       *zbuffer = (UINT *)_zbuffer;
  1254. #ifdef DEBUG_ON
  1255. // track rendering stats
  1256.     debug_polys_rendered_per_frame++;
  1257. #endif
  1258. // extract texture map
  1259. textmap = (USHORT *)face->texture->buffer;
  1260. // extract base 2 of texture width
  1261. int texture_shift2 = logbase2ofx[face->texture->width];
  1262. // adjust memory pitch to words, divide by 2
  1263. mem_pitch >>=1;
  1264. // adjust zbuffer pitch for 32 bit alignment
  1265. zpitch >>= 2;
  1266. // apply fill convention to coordinates
  1267. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  1268. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  1269. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  1270. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  1271. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  1272. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  1273. // first trivial clipping rejection tests 
  1274. if (((face->tvlist[0].y < min_clip_y)  && 
  1275.  (face->tvlist[1].y < min_clip_y)  &&
  1276.  (face->tvlist[2].y < min_clip_y)) ||
  1277. ((face->tvlist[0].y > max_clip_y)  && 
  1278.  (face->tvlist[1].y > max_clip_y)  &&
  1279.  (face->tvlist[2].y > max_clip_y)) ||
  1280. ((face->tvlist[0].x < min_clip_x)  && 
  1281.  (face->tvlist[1].x < min_clip_x)  &&
  1282.  (face->tvlist[2].x < min_clip_x)) ||
  1283. ((face->tvlist[0].x > max_clip_x)  && 
  1284.  (face->tvlist[1].x > max_clip_x)  &&
  1285.  (face->tvlist[2].x > max_clip_x)))
  1286.    return;
  1287. // sort vertices
  1288. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  1289. {SWAP(v0,v1,temp);} 
  1290. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  1291. {SWAP(v0,v2,temp);}
  1292. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  1293. {SWAP(v1,v2,temp);}
  1294. // now test for trivial flat sided cases
  1295. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  1296. // set triangle type
  1297. tri_type = TRI_TYPE_FLAT_TOP;
  1298. // sort vertices left to right
  1299. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  1300. {SWAP(v0,v1,temp);}
  1301. } // end if
  1302. else
  1303. // now test for trivial flat sided cases
  1304. if (FCMP( face->tvlist[v1].y, face->tvlist[v2].y) )
  1305. // set triangle type
  1306. tri_type = TRI_TYPE_FLAT_BOTTOM;
  1307. // sort vertices left to right
  1308. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  1309. {SWAP(v1,v2,temp);}
  1310. } // end if
  1311. else
  1312. {
  1313. // must be a general triangle
  1314. tri_type = TRI_TYPE_GENERAL;
  1315. } // end else
  1316. // extract base color of lit poly, so we can modulate texture a bit
  1317. // for lighting
  1318. _RGB565FROM16BIT(face->lit_color[0], &r_base, &g_base, &b_base);
  1319. // extract vertices for processing, now that we have order
  1320. x0  = (int)(face->tvlist[v0].x+0.0);
  1321. y0  = (int)(face->tvlist[v0].y+0.0);
  1322. tu0 = (int)(face->tvlist[v0].u0);
  1323. tv0 = (int)(face->tvlist[v0].v0);
  1324. tz0 = (int)(face->tvlist[v0].z+0.5);
  1325. x1  = (int)(face->tvlist[v1].x+0.0);
  1326. y1  = (int)(face->tvlist[v1].y+0.0);
  1327. tu1 = (int)(face->tvlist[v1].u0);
  1328. tv1 = (int)(face->tvlist[v1].v0);
  1329. tz1 = (int)(face->tvlist[v1].z+0.5);
  1330. x2  = (int)(face->tvlist[v2].x+0.0);
  1331. y2  = (int)(face->tvlist[v2].y+0.0);
  1332. tu2 = (int)(face->tvlist[v2].u0);
  1333. tv2 = (int)(face->tvlist[v2].v0);
  1334. tz2 = (int)(face->tvlist[v2].z+0.5);
  1335. // degenerate triangle
  1336. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  1337.    return;
  1338. // set interpolation restart value
  1339. yrestart = y1;
  1340. // what kind of triangle
  1341. if (tri_type & TRI_TYPE_FLAT_MASK)
  1342. {
  1343. if (tri_type == TRI_TYPE_FLAT_TOP)
  1344. {
  1345. // compute all deltas
  1346. dy = (y2 - y0);
  1347. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1348. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1349. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  1350. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  1351. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  1352. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  1353. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  1354. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;   
  1355. // test for y clipping
  1356. if (y0 < min_clip_y)
  1357. {
  1358. // compute overclip
  1359. dy = (min_clip_y - y0);
  1360. // computer new LHS starting values
  1361. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1362. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1363. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1364. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1365. // compute new RHS starting values
  1366. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  1367. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  1368. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  1369. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  1370. // compute new starting y
  1371. ystart = min_clip_y;
  1372. } // end if
  1373. else
  1374. {
  1375. // no clipping
  1376. // set starting values
  1377. xl = (x0 << FIXP16_SHIFT);
  1378. xr = (x1 << FIXP16_SHIFT);
  1379. ul = (tu0 << FIXP16_SHIFT);
  1380. vl = (tv0 << FIXP16_SHIFT);
  1381. zl = (tz0 << FIXP16_SHIFT);
  1382. ur = (tu1 << FIXP16_SHIFT);
  1383. vr = (tv1 << FIXP16_SHIFT);
  1384. zr = (tz1 << FIXP16_SHIFT);
  1385. // set starting y
  1386. ystart = y0;
  1387. } // end else
  1388. } // end if flat top
  1389. else
  1390. {
  1391. // must be flat bottom
  1392. // compute all deltas
  1393. dy = (y1 - y0);
  1394. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  1395. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  1396. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  1397. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy; 
  1398. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1399. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1400. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  1401. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  1402. // test for y clipping
  1403. if (y0 < min_clip_y)
  1404. {
  1405. // compute overclip
  1406. dy = (min_clip_y - y0);
  1407. // computer new LHS starting values
  1408. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1409. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1410. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1411. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1412. // compute new RHS starting values
  1413. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1414. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1415. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1416. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1417. // compute new starting y
  1418. ystart = min_clip_y;
  1419. } // end if
  1420. else
  1421. {
  1422. // no clipping
  1423. // set starting values
  1424. xl = (x0 << FIXP16_SHIFT);
  1425. xr = (x0 << FIXP16_SHIFT);
  1426. ul = (tu0 << FIXP16_SHIFT);
  1427. vl = (tv0 << FIXP16_SHIFT);
  1428. zl = (tz0 << FIXP16_SHIFT);
  1429. ur = (tu0 << FIXP16_SHIFT);
  1430. vr = (tv0 << FIXP16_SHIFT);
  1431. zr = (tz0 << FIXP16_SHIFT);
  1432. // set starting y
  1433. ystart = y0;
  1434. } // end else
  1435. } // end else flat bottom
  1436. // test for bottom clip, always
  1437. if ((yend = y2) > max_clip_y)
  1438. yend = max_clip_y;
  1439.     // test for horizontal clipping
  1440. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1441. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1442. (x2 < min_clip_x) || (x2 > max_clip_x))
  1443. {
  1444.     // clip version
  1445. // point screen ptr to starting line
  1446. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1447.     // point zbuffer to starting line
  1448.     z_ptr = zbuffer + (ystart * zpitch);
  1449. for (yi = ystart; yi < yend; yi++)
  1450. {
  1451. // compute span endpoints
  1452. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1453. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1454. // compute starting points for u,v interpolants
  1455. ui = ul + FIXP16_ROUND_UP;
  1456. vi = vl + FIXP16_ROUND_UP;
  1457. zi = zl + FIXP16_ROUND_UP;
  1458. // compute u,v interpolants
  1459. if ((dx = (xend - xstart))>0)
  1460. {
  1461. du = (ur - ul)/dx;
  1462. dv = (vr - vl)/dx;
  1463. dz = (zr - zl)/dx;
  1464. } // end if
  1465. else
  1466. {
  1467. du = (ur - ul);
  1468. dv = (vr - vl);
  1469. dz = (zr - zl);
  1470. } // end else
  1471. ///////////////////////////////////////////////////////////////////////
  1472. // test for x clipping, LHS
  1473. if (xstart < min_clip_x)
  1474. {
  1475. // compute x overlap
  1476. dx = min_clip_x - xstart;
  1477. // slide interpolants over
  1478. ui+=dx*du;
  1479. vi+=dx*dv;
  1480. zi+=dx*dz;
  1481. // reset vars
  1482. xstart = min_clip_x;
  1483. } // end if
  1484. // test for x clipping RHS
  1485. if (xend > max_clip_x)
  1486. xend = max_clip_x;
  1487. ///////////////////////////////////////////////////////////////////////
  1488. // draw span
  1489. for (xi=xstart; xi < xend; xi++)
  1490. {
  1491.             // write thru the z buffer always
  1492.    // write textel
  1493.        // get textel first
  1494.      textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1495.                // extract rgb components
  1496.                r_textel  = ((textel >> 11)       ); 
  1497.                g_textel  = ((textel >> 5)  & 0x3f); 
  1498.                b_textel =   (textel        & 0x1f);
  1499.                // modulate textel with lit background color
  1500.                r_textel*=r_base; 
  1501.                g_textel*=g_base;
  1502.                b_textel*=b_base;
  1503.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  1504.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  1505.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  1506.                // and they all cancel out for the most part, but we will need logical anding, we will do
  1507.                // it later when we optimize more...
  1508.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  1509.                // update z-buffer
  1510.                z_ptr[xi] = zi;           
  1511. // interpolate u,v,z
  1512. ui+=du;
  1513. vi+=dv;
  1514. zi+=dz;
  1515. } // end for xi
  1516. // interpolate u,v,x along right and left edge
  1517. xl+=dxdyl;
  1518. ul+=dudyl;
  1519. vl+=dvdyl;
  1520. zl+=dzdyl;
  1521. xr+=dxdyr;
  1522. ur+=dudyr;
  1523. vr+=dvdyr;
  1524. zr+=dzdyr;
  1525.  
  1526. // advance screen ptr
  1527. screen_ptr+=mem_pitch;
  1528.         // advance zbuffer ptr
  1529.         z_ptr+=zpitch;
  1530. } // end for y
  1531. } // end if clip
  1532. else
  1533. {
  1534. // non-clip version
  1535. // point screen ptr to starting line
  1536. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1537.     // point zbuffer to starting line
  1538.     z_ptr = zbuffer + (ystart * zpitch);
  1539. for (yi = ystart; yi < yend; yi++)
  1540. {
  1541. // compute span endpoints
  1542. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1543. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1544. // compute starting points for u,v interpolants
  1545. ui = ul + FIXP16_ROUND_UP;
  1546. vi = vl + FIXP16_ROUND_UP;
  1547. zi = zl + FIXP16_ROUND_UP;
  1548. // compute u,v interpolants
  1549. if ((dx = (xend - xstart))>0)
  1550. {
  1551. du = (ur - ul)/dx;
  1552. dv = (vr - vl)/dx;
  1553. dz = (zr - zl)/dx;
  1554. } // end if
  1555. else
  1556. {
  1557. du = (ur - ul);
  1558. dv = (vr - vl);
  1559.             dz = (zr - zl);
  1560. } // end else
  1561. // draw span
  1562. for (xi=xstart; xi < xend; xi++)
  1563. {
  1564.             // write thru the z buffer always
  1565.    // write textel
  1566.        // get textel first
  1567.      textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1568.                // extract rgb components
  1569.                r_textel  = ((textel >> 11)       ); 
  1570.                g_textel  = ((textel >> 5)  & 0x3f); 
  1571.                b_textel =   (textel        & 0x1f);
  1572.                // modulate textel with lit background color
  1573.                r_textel*=r_base; 
  1574.                g_textel*=g_base;
  1575.                b_textel*=b_base;
  1576.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  1577.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  1578.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  1579.                // and they all cancel out for the most part, but we will need logical anding, we will do
  1580.                // it later when we optimize more...
  1581.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  1582.                // update z-buffer
  1583.                z_ptr[xi] = zi;     
  1584. // interpolate u,v,z
  1585. ui+=du;
  1586. vi+=dv;
  1587.             zi+=dz;
  1588. } // end for xi
  1589. // interpolate u,v,x along right and left edge
  1590. xl+=dxdyl;
  1591. ul+=dudyl;
  1592. vl+=dvdyl;
  1593.     zl+=dzdyl;
  1594. xr+=dxdyr;
  1595. ur+=dudyr;
  1596. vr+=dvdyr;
  1597.         zr+=dzdyr;
  1598. // advance screen ptr
  1599. screen_ptr+=mem_pitch;
  1600.         // advance zbuffer ptr
  1601.         z_ptr+=zpitch;
  1602. } // end for y
  1603. } // end if non-clipped
  1604. } // end if
  1605. else
  1606. if (tri_type==TRI_TYPE_GENERAL)
  1607. {
  1608. // first test for bottom clip, always
  1609. if ((yend = y2) > max_clip_y)
  1610. yend = max_clip_y;
  1611. // pre-test y clipping status
  1612. if (y1 < min_clip_y)
  1613. {
  1614. // compute all deltas
  1615. // LHS
  1616. dyl = (y2 - y1);
  1617. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  1618. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1619. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  1620.         dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;    
  1621. // RHS
  1622. dyr = (y2 - y0);
  1623. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1624. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1625. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1626.         dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  1627. // compute overclip
  1628. dyr = (min_clip_y - y0);
  1629. dyl = (min_clip_y - y1);
  1630. // computer new LHS starting values
  1631. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  1632. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  1633. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  1634.         zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  1635. // compute new RHS starting values
  1636. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  1637. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  1638. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  1639.         zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  1640. // compute new starting y
  1641. ystart = min_clip_y;
  1642. // test if we need swap to keep rendering left to right
  1643. if (dxdyr > dxdyl)
  1644. {
  1645. SWAP(dxdyl,dxdyr,temp);
  1646. SWAP(dudyl,dudyr,temp);
  1647. SWAP(dvdyl,dvdyr,temp);
  1648. SWAP(dzdyl,dzdyr,temp);
  1649. SWAP(xl,xr,temp);
  1650. SWAP(ul,ur,temp);
  1651. SWAP(vl,vr,temp);
  1652. SWAP(zl,zr,temp);
  1653. SWAP(x1,x2,temp);
  1654. SWAP(y1,y2,temp);
  1655. SWAP(tu1,tu2,temp);
  1656. SWAP(tv1,tv2,temp);
  1657. SWAP(tz1,tz2,temp);
  1658. // set interpolation restart
  1659. irestart = INTERP_RHS;
  1660. } // end if
  1661. } // end if
  1662. else
  1663. if (y0 < min_clip_y)
  1664. {
  1665. // compute all deltas
  1666. // LHS
  1667. dyl = (y1 - y0);
  1668. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1669. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1670. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1671.         dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;    
  1672. // RHS
  1673. dyr = (y2 - y0);
  1674. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1675. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1676. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1677.         dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  1678. // compute overclip
  1679. dy = (min_clip_y - y0);
  1680. // computer new LHS starting values
  1681. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1682. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1683. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1684.         zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1685. // compute new RHS starting values
  1686. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1687. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1688. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1689.         zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1690. // compute new starting y
  1691. ystart = min_clip_y;
  1692. // test if we need swap to keep rendering left to right
  1693. if (dxdyr < dxdyl)
  1694. {
  1695. SWAP(dxdyl,dxdyr,temp);
  1696. SWAP(dudyl,dudyr,temp);
  1697. SWAP(dvdyl,dvdyr,temp);
  1698. SWAP(dzdyl,dzdyr,temp);
  1699. SWAP(xl,xr,temp);
  1700. SWAP(ul,ur,temp);
  1701. SWAP(vl,vr,temp);
  1702. SWAP(zl,zr,temp);
  1703. SWAP(x1,x2,temp);
  1704. SWAP(y1,y2,temp);
  1705. SWAP(tu1,tu2,temp);
  1706. SWAP(tv1,tv2,temp);
  1707. SWAP(tz1,tz2,temp);
  1708. // set interpolation restart
  1709. irestart = INTERP_RHS;
  1710. } // end if
  1711. } // end if
  1712. else
  1713. {
  1714. // no initial y clipping
  1715. // compute all deltas
  1716. // LHS
  1717. dyl = (y1 - y0);
  1718. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1719. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1720. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1721.         dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;    
  1722. // RHS
  1723. dyr = (y2 - y0);
  1724. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  1725. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1726. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1727.         dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  1728. // no clipping y
  1729. // set starting values
  1730. xl = (x0 << FIXP16_SHIFT);
  1731. xr = (x0 << FIXP16_SHIFT);
  1732. ul = (tu0 << FIXP16_SHIFT);
  1733. vl = (tv0 << FIXP16_SHIFT);
  1734.         zl = (tz0 << FIXP16_SHIFT);
  1735. ur = (tu0 << FIXP16_SHIFT);
  1736. vr = (tv0 << FIXP16_SHIFT);
  1737.         zr = (tz0 << FIXP16_SHIFT);
  1738. // set starting y
  1739. ystart = y0;
  1740. // test if we need swap to keep rendering left to right
  1741. if (dxdyr < dxdyl)
  1742. {
  1743. SWAP(dxdyl,dxdyr,temp);
  1744. SWAP(dudyl,dudyr,temp);
  1745. SWAP(dvdyl,dvdyr,temp);
  1746. SWAP(dzdyl,dzdyr,temp);
  1747. SWAP(xl,xr,temp);
  1748. SWAP(ul,ur,temp);
  1749. SWAP(vl,vr,temp);
  1750. SWAP(zl,zr,temp);
  1751. SWAP(x1,x2,temp);
  1752. SWAP(y1,y2,temp);
  1753. SWAP(tu1,tu2,temp);
  1754. SWAP(tv1,tv2,temp);
  1755. SWAP(tz1,tz2,temp);
  1756. // set interpolation restart
  1757. irestart = INTERP_RHS;
  1758. } // end if
  1759. } // end else
  1760.     // test for horizontal clipping
  1761. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1762. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1763. (x2 < min_clip_x) || (x2 > max_clip_x))
  1764. {
  1765.     // clip version
  1766. // x clipping
  1767. // point screen ptr to starting line
  1768. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1769.     // point zbuffer to starting line
  1770.     z_ptr = zbuffer + (ystart * zpitch);
  1771. for (yi = ystart; yi < yend; yi++)
  1772. {
  1773. // compute span endpoints
  1774. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1775. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1776. // compute starting points for u,v interpolants
  1777. ui = ul + FIXP16_ROUND_UP;
  1778. vi = vl + FIXP16_ROUND_UP;
  1779.         zi = zl + FIXP16_ROUND_UP;
  1780. // compute u,v interpolants
  1781. if ((dx = (xend - xstart))>0)
  1782. {
  1783. du = (ur - ul)/dx;
  1784. dv = (vr - vl)/dx;
  1785.             dz = (zr - zl)/dx;
  1786. } // end if
  1787. else
  1788. {
  1789. du = (ur - ul);
  1790. dv = (vr - vl);
  1791.             dz = (zr - zl);
  1792. } // end else
  1793. ///////////////////////////////////////////////////////////////////////
  1794. // test for x clipping, LHS
  1795. if (xstart < min_clip_x)
  1796. {
  1797. // compute x overlap
  1798. dx = min_clip_x - xstart;
  1799. // slide interpolants over
  1800. ui+=dx*du;
  1801. vi+=dx*dv;
  1802. zi+=dx*dz;
  1803. // set x to left clip edge
  1804. xstart = min_clip_x;
  1805. } // end if
  1806. // test for x clipping RHS
  1807. if (xend > max_clip_x)
  1808. xend = max_clip_x;
  1809. ///////////////////////////////////////////////////////////////////////
  1810. // draw span
  1811. for (xi=xstart; xi < xend; xi++)
  1812. {
  1813.             // write thru the z buffer always
  1814.    // write textel
  1815.        // get textel first
  1816.      textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1817.                // extract rgb components
  1818.                r_textel  = ((textel >> 11)       ); 
  1819.                g_textel  = ((textel >> 5)  & 0x3f); 
  1820.                b_textel =   (textel        & 0x1f);
  1821.                // modulate textel with lit background color
  1822.                r_textel*=r_base; 
  1823.                g_textel*=g_base;
  1824.                b_textel*=b_base;
  1825.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  1826.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  1827.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  1828.                // and they all cancel out for the most part, but we will need logical anding, we will do
  1829.                // it later when we optimize more...
  1830.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  1831.                // update z-buffer
  1832.                z_ptr[xi] = zi;     
  1833. // interpolate u,v
  1834. ui+=du;
  1835. vi+=dv;
  1836.             zi+=dz;
  1837. } // end for xi
  1838. // interpolate u,v,x along right and left edge
  1839. xl+=dxdyl;
  1840. ul+=dudyl;
  1841. vl+=dvdyl;
  1842. zl+=dzdyl;
  1843. xr+=dxdyr;
  1844. ur+=dudyr;
  1845. vr+=dvdyr;
  1846. zr+=dzdyr;
  1847. // advance screen ptr
  1848. screen_ptr+=mem_pitch;
  1849.         // advance zbuffer ptr
  1850.         z_ptr+=zpitch;
  1851. // test for yi hitting second region, if so change interpolant
  1852. if (yi==yrestart)
  1853. {
  1854.       // test interpolation side change flag
  1855. if (irestart == INTERP_LHS)
  1856. {
  1857. // LHS
  1858. dyl = (y2 - y1);
  1859. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1860. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1861. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1862. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  1863. // set starting values
  1864. xl = (x1  << FIXP16_SHIFT);
  1865. ul = (tu1 << FIXP16_SHIFT);
  1866. vl = (tv1 << FIXP16_SHIFT);
  1867. zl = (tz1 << FIXP16_SHIFT);
  1868. // interpolate down on LHS to even up
  1869. xl+=dxdyl;
  1870. ul+=dudyl;
  1871. vl+=dvdyl;
  1872. zl+=dzdyl;
  1873. } // end if
  1874. else
  1875. {
  1876. // RHS
  1877. dyr = (y1 - y2);
  1878. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1879. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1880. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1881. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  1882. // set starting values
  1883. xr = (x2  << FIXP16_SHIFT);
  1884. ur = (tu2 << FIXP16_SHIFT);
  1885. vr = (tv2 << FIXP16_SHIFT);
  1886. zr = (tz2 << FIXP16_SHIFT);
  1887. // interpolate down on RHS to even up
  1888. xr+=dxdyr;
  1889. ur+=dudyr;
  1890. vr+=dvdyr;
  1891. zr+=dzdyr;
  1892. } // end else
  1893. } // end if
  1894. } // end for y
  1895. } // end if
  1896. else
  1897. {
  1898. // no x clipping
  1899. // point screen ptr to starting line
  1900. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1901.     // point zbuffer to starting line
  1902.     z_ptr = zbuffer + (ystart * zpitch);
  1903. for (yi = ystart; yi < yend; yi++)
  1904. {
  1905. // compute span endpoints
  1906. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1907. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1908. // compute starting points for u,v,z interpolants
  1909. ui = ul + FIXP16_ROUND_UP;
  1910. vi = vl + FIXP16_ROUND_UP;
  1911. zi = zl + FIXP16_ROUND_UP;
  1912. // compute u,v interpolants
  1913. if ((dx = (xend - xstart))>0)
  1914. {
  1915. du = (ur - ul)/dx;
  1916. dv = (vr - vl)/dx;
  1917.             dz = (zr - zl)/dx;
  1918. } // end if
  1919. else
  1920. {
  1921. du = (ur - ul);
  1922. dv = (vr - vl);
  1923.             dz = (zr - zl);
  1924. } // end else
  1925. // draw span
  1926. for (xi=xstart; xi < xend; xi++)
  1927. {
  1928.             // write thru the z buffer always
  1929.    // write textel
  1930.        // get textel first
  1931.      textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1932.                // extract rgb components
  1933.                r_textel  = ((textel >> 11)       ); 
  1934.                g_textel  = ((textel >> 5)  & 0x3f); 
  1935.                b_textel =   (textel        & 0x1f);
  1936.                // modulate textel with lit background color
  1937.                r_textel*=r_base; 
  1938.                g_textel*=g_base;
  1939.                b_textel*=b_base;
  1940.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  1941.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  1942.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  1943.                // and they all cancel out for the most part, but we will need logical anding, we will do
  1944.                // it later when we optimize more...
  1945.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  1946.                // update z-buffer
  1947.                z_ptr[xi] = zi;     
  1948. // interpolate u,v,z
  1949. ui+=du;
  1950. vi+=dv;
  1951.             zi+=dz;
  1952. } // end for xi
  1953. // interpolate u,v,x along right and left edge
  1954. xl+=dxdyl;
  1955. ul+=dudyl;
  1956. vl+=dvdyl;
  1957.         zl+=dzdyl;
  1958. xr+=dxdyr;
  1959. ur+=dudyr;
  1960. vr+=dvdyr;
  1961.         zr+=dzdyr;
  1962. // advance screen ptr
  1963. screen_ptr+=mem_pitch;
  1964.         // advance zbuffer ptr
  1965.         z_ptr+=zpitch;
  1966. // test for yi hitting second region, if so change interpolant
  1967. if (yi==yrestart)
  1968. {
  1969. // test interpolation side change flag
  1970. if (irestart == INTERP_LHS)
  1971. {
  1972. // LHS
  1973. dyl = (y2 - y1);
  1974. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1975. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1976. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1977. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl; 
  1978. // set starting values
  1979. xl = (x1  << FIXP16_SHIFT);
  1980. ul = (tu1 << FIXP16_SHIFT);
  1981. vl = (tv1 << FIXP16_SHIFT);
  1982. zl = (tz1 << FIXP16_SHIFT);
  1983. // interpolate down on LHS to even up
  1984. xl+=dxdyl;
  1985. ul+=dudyl;
  1986. vl+=dvdyl;
  1987. zl+=dzdyl;
  1988. } // end if
  1989. else
  1990. {
  1991. // RHS
  1992. dyr = (y1 - y2);
  1993. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1994. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1995. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1996. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  1997. // set starting values
  1998. xr = (x2  << FIXP16_SHIFT);
  1999. ur = (tu2 << FIXP16_SHIFT);
  2000. vr = (tv2 << FIXP16_SHIFT);
  2001. zr = (tz2 << FIXP16_SHIFT);
  2002. // interpolate down on RHS to even up
  2003. xr+=dxdyr;
  2004. ur+=dudyr;
  2005. vr+=dvdyr;
  2006. zr+=dzdyr;
  2007. } // end else
  2008. } // end if
  2009. } // end for y
  2010.    } // end else
  2011. } // end if
  2012. } // end Draw_Textured_TriangleFSWTZB2_16
  2013. //////////////////////////////////////////////////////////////////////////////
  2014. //////////////////////////////////////////////////////////////////////////////
  2015. void Draw_Textured_TriangleGSWTZB_16(POLYF4DV2_PTR face,   // ptr to face
  2016.                                  UCHAR *_dest_buffer, // pointer to video buffer
  2017.                                  int mem_pitch,       // bytes per line, 320, 640 etc.
  2018.                                  UCHAR *_zbuffer,       // pointer to z-buffer
  2019.                                  int zpitch)          // bytes per line of zbuffer
  2020. {
  2021. // this function draws a textured gouraud shaded polygon, and z bufferedbased on the affine texture mapper, 
  2022. // we simply interpolate the (R,G,B) values across the polygons along with the texture coordinates
  2023. // and then modulate to get the final color 
  2024. int v0=0,
  2025.     v1=1,
  2026. v2=2,
  2027. temp=0,
  2028. tri_type = TRI_TYPE_NONE,
  2029. irestart = INTERP_LHS;
  2030. int dx,dy,dyl,dyr,      // general deltas
  2031.     u,v,w,z, s,t,
  2032.     du,dv,dw,dz, ds, dt, 
  2033.     xi,yi,             // the current interpolated x,y
  2034. ui,vi,wi,zi, si, ti,    // the current interpolated u,v
  2035. index_x,index_y,    // looping vars
  2036. x,y,                // hold general x,y
  2037. xstart,
  2038. xend,
  2039. ystart,
  2040. yrestart,
  2041. yend,
  2042. xl,                 
  2043. dxdyl,              
  2044. xr,
  2045. dxdyr,             
  2046. dudyl,    
  2047. ul,
  2048. dvdyl,   
  2049. vl,
  2050. dwdyl,   
  2051. wl,
  2052. dzdyl,   
  2053. zl,
  2054. dsdyl,    
  2055. sl,
  2056. dtdyl,   
  2057. tl,
  2058. dudyr,
  2059. ur,
  2060. dvdyr,
  2061. vr,
  2062. dwdyr,
  2063. wr,
  2064. dzdyr,
  2065. zr,
  2066. dsdyr,
  2067. sr,
  2068. dtdyr,
  2069. tr;
  2070. int x0,y0,tu0,tv0,tw0, tz0, ts0,tt0,    // cached vertices
  2071. x1,y1,tu1,tv1,tw1, tz1, ts1,tt1,
  2072. x2,y2,tu2,tv2,tw2, tz2, ts2,tt2;
  2073. int r_base0, g_base0, b_base0,
  2074.     r_base1, g_base1, b_base1,
  2075.     r_base2, g_base2, b_base2;
  2076. UINT r_textel, g_textel, b_textel;
  2077. USHORT textel;
  2078. USHORT *screen_ptr  = NULL,
  2079.    *screen_line = NULL,
  2080.    *textmap     = NULL,
  2081.        *dest_buffer = (USHORT *)_dest_buffer;
  2082. UINT  *z_ptr = NULL,
  2083.       *zbuffer = (UINT *)_zbuffer;
  2084. #ifdef DEBUG_ON
  2085. // track rendering stats
  2086.     debug_polys_rendered_per_frame++;
  2087. #endif
  2088. // extract texture map
  2089. textmap = (USHORT *)face->texture->buffer;
  2090. // extract base 2 of texture width
  2091. int texture_shift2 = logbase2ofx[face->texture->width];
  2092. // adjust memory pitch to words, divide by 2
  2093. mem_pitch >>=1;
  2094. // adjust zbuffer pitch for 32 bit alignment
  2095. zpitch >>= 2;
  2096. // apply fill convention to coordinates
  2097. face->tvlist[0].x = (int)(face->tvlist[0].x+0.0);
  2098. face->tvlist[0].y = (int)(face->tvlist[0].y+0.0);
  2099. face->tvlist[1].x = (int)(face->tvlist[1].x+0.0);
  2100. face->tvlist[1].y = (int)(face->tvlist[1].y+0.0);
  2101. face->tvlist[2].x = (int)(face->tvlist[2].x+0.0);
  2102. face->tvlist[2].y = (int)(face->tvlist[2].y+0.0);
  2103. // first trivial clipping rejection tests 
  2104. if (((face->tvlist[0].y < min_clip_y)  && 
  2105.  (face->tvlist[1].y < min_clip_y)  &&
  2106.  (face->tvlist[2].y < min_clip_y)) ||
  2107. ((face->tvlist[0].y > max_clip_y)  && 
  2108.  (face->tvlist[1].y > max_clip_y)  &&
  2109.  (face->tvlist[2].y > max_clip_y)) ||
  2110. ((face->tvlist[0].x < min_clip_x)  && 
  2111.  (face->tvlist[1].x < min_clip_x)  &&
  2112.  (face->tvlist[2].x < min_clip_x)) ||
  2113. ((face->tvlist[0].x > max_clip_x)  && 
  2114.  (face->tvlist[1].x > max_clip_x)  &&
  2115.  (face->tvlist[2].x > max_clip_x)))
  2116.    return;
  2117. // sort vertices
  2118. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  2119. {SWAP(v0,v1,temp);} 
  2120. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  2121. {SWAP(v0,v2,temp);}
  2122. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  2123. {SWAP(v1,v2,temp);}
  2124. // now test for trivial flat sided cases
  2125. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  2126. // set triangle type
  2127. tri_type = TRI_TYPE_FLAT_TOP;
  2128. // sort vertices left to right
  2129. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  2130. {SWAP(v0,v1,temp);}
  2131. } // end if
  2132. else
  2133. // now test for trivial flat sided cases
  2134. if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
  2135. // set triangle type
  2136. tri_type = TRI_TYPE_FLAT_BOTTOM;
  2137. // sort vertices left to right
  2138. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  2139. {SWAP(v1,v2,temp);}
  2140. } // end if
  2141. else
  2142. {
  2143. // must be a general triangle
  2144. tri_type = TRI_TYPE_GENERAL;
  2145. } // end else
  2146. // assume 5.6.5 format -- sorry!
  2147. // we can't afford a function call in the inner loops, so we must write 
  2148. // two hard coded versions, if we want support for both 5.6.5, and 5.5.5
  2149. _RGB565FROM16BIT(face->lit_color[v0], &r_base0, &g_base0, &b_base0);
  2150. _RGB565FROM16BIT(face->lit_color[v1], &r_base1, &g_base1, &b_base1);
  2151. _RGB565FROM16BIT(face->lit_color[v2], &r_base2, &g_base2, &b_base2);
  2152. // scale to 8 bit 
  2153. r_base0 <<= 3;
  2154. g_base0 <<= 2;
  2155. b_base0 <<= 3;
  2156. // scale to 8 bit 
  2157. r_base1 <<= 3;
  2158. g_base1 <<= 2;
  2159. b_base1 <<= 3;
  2160. // scale to 8 bit 
  2161. r_base2 <<= 3;
  2162. g_base2 <<= 2;
  2163. b_base2 <<= 3;
  2164. // extract vertices for processing, now that we have order
  2165. x0  = (int)(face->tvlist[v0].x+0.0);
  2166. y0  = (int)(face->tvlist[v0].y+0.0);
  2167. tz0 = (int)(face->tvlist[v0].z+0.5);
  2168. ts0 = (int)(face->tvlist[v0].u0);
  2169. tt0 = (int)(face->tvlist[v0].v0);
  2170. tu0 = r_base0;
  2171. tv0 = g_base0; 
  2172. tw0 = b_base0; 
  2173. x1  = (int)(face->tvlist[v1].x+0.0);
  2174. y1  = (int)(face->tvlist[v1].y+0.0);
  2175. tz1 = (int)(face->tvlist[v1].z+0.5);
  2176. ts1 = (int)(face->tvlist[v1].u0);
  2177. tt1 = (int)(face->tvlist[v1].v0);
  2178. tu1 = r_base1;
  2179. tv1 = g_base1; 
  2180. tw1 = b_base1; 
  2181. x2  = (int)(face->tvlist[v2].x+0.0);
  2182. y2  = (int)(face->tvlist[v2].y+0.0);
  2183. tz2 = (int)(face->tvlist[v2].z+0.5);
  2184. ts2 = (int)(face->tvlist[v2].u0);
  2185. tt2 = (int)(face->tvlist[v2].v0);
  2186. tu2 = r_base2; 
  2187. tv2 = g_base2; 
  2188. tw2 = b_base2; 
  2189. // degenerate triangle
  2190. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  2191.    return;
  2192. // set interpolation restart value
  2193. yrestart = y1;
  2194. // what kind of triangle
  2195. if (tri_type & TRI_TYPE_FLAT_MASK)
  2196. {
  2197. if (tri_type == TRI_TYPE_FLAT_TOP)
  2198. {
  2199. // compute all deltas
  2200. dy = (y2 - y0);
  2201. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2202. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2203. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  2204. dwdyl = ((tw2 - tw0) << FIXP16_SHIFT)/dy;  
  2205. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy; 
  2206.     dsdyl = ((ts2 - ts0) << FIXP16_SHIFT)/dy;    
  2207. dtdyl = ((tt2 - tt0) << FIXP16_SHIFT)/dy;  
  2208. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  2209. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  2210. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  2211. dwdyr = ((tw2 - tw1) << FIXP16_SHIFT)/dy;   
  2212. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;   
  2213. dsdyr = ((ts2 - ts1) << FIXP16_SHIFT)/dy;   
  2214. dtdyr = ((tt2 - tt1) << FIXP16_SHIFT)/dy;   
  2215. // test for y clipping
  2216. if (y0 < min_clip_y)
  2217. {
  2218. // compute overclip
  2219. dy = (min_clip_y - y0);
  2220. // computer new LHS starting values
  2221. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2222. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2223. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2224. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  2225. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2226. sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
  2227. tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
  2228. // compute new RHS starting values
  2229. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  2230. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  2231. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  2232. wr = dwdyr*dy + (tw1 << FIXP16_SHIFT);
  2233. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  2234. sr = dsdyr*dy + (ts1 << FIXP16_SHIFT);
  2235. tr = dtdyr*dy + (tt1 << FIXP16_SHIFT);
  2236. // compute new starting y
  2237. ystart = min_clip_y;
  2238. } // end if
  2239. else
  2240. {
  2241. // no clipping
  2242. // set starting values
  2243. xl = (x0 << FIXP16_SHIFT);
  2244. xr = (x1 << FIXP16_SHIFT);
  2245. ul = (tu0 << FIXP16_SHIFT);
  2246. vl = (tv0 << FIXP16_SHIFT);
  2247. wl = (tw0 << FIXP16_SHIFT);
  2248. zl = (tz0 << FIXP16_SHIFT);
  2249. sl = (ts0 << FIXP16_SHIFT);
  2250. tl = (tt0 << FIXP16_SHIFT);
  2251. ur = (tu1 << FIXP16_SHIFT);
  2252. vr = (tv1 << FIXP16_SHIFT);
  2253. wr = (tw1 << FIXP16_SHIFT);
  2254. zr = (tz1 << FIXP16_SHIFT);
  2255. sr = (ts1 << FIXP16_SHIFT);
  2256. tr = (tt1 << FIXP16_SHIFT);
  2257. // set starting y
  2258. ystart = y0;
  2259. } // end else
  2260. } // end if flat top
  2261. else
  2262. {
  2263. // must be flat bottom
  2264. // compute all deltas
  2265. dy = (y1 - y0);
  2266. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  2267. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  2268. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  2269. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dy; 
  2270. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy; 
  2271. dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dy;    
  2272. dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dy; 
  2273. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2274. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2275. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  2276. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dy;   
  2277. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  2278. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dy;   
  2279. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dy;   
  2280. // test for y clipping
  2281. if (y0 < min_clip_y)
  2282. {
  2283. // compute overclip
  2284. dy = (min_clip_y - y0);
  2285. // computer new LHS starting values
  2286. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2287. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2288. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2289. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  2290. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2291. sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
  2292. tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
  2293. // compute new RHS starting values
  2294. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2295. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2296. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2297. wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
  2298. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  2299. sr = dsdyr*dy + (ts0 << FIXP16_SHIFT);
  2300. tr = dtdyr*dy + (tt0 << FIXP16_SHIFT);
  2301. // compute new starting y
  2302. ystart = min_clip_y;
  2303. } // end if
  2304. else
  2305. {
  2306. // no clipping
  2307. // set starting values
  2308. xl = (x0 << FIXP16_SHIFT);
  2309. xr = (x0 << FIXP16_SHIFT);
  2310. ul = (tu0 << FIXP16_SHIFT);
  2311. vl = (tv0 << FIXP16_SHIFT);
  2312. wl = (tw0 << FIXP16_SHIFT);
  2313. zl = (tz0 << FIXP16_SHIFT);
  2314. sl = (ts0 << FIXP16_SHIFT);
  2315. tl = (tt0 << FIXP16_SHIFT);
  2316. ur = (tu0 << FIXP16_SHIFT);
  2317. vr = (tv0 << FIXP16_SHIFT);
  2318. wr = (tw0 << FIXP16_SHIFT);
  2319. zr = (tz0 << FIXP16_SHIFT);
  2320. sr = (ts0 << FIXP16_SHIFT);
  2321. tr = (tt0 << FIXP16_SHIFT);
  2322. // set starting y
  2323. ystart = y0;
  2324. } // end else
  2325. } // end else flat bottom
  2326. // test for bottom clip, always
  2327. if ((yend = y2) > max_clip_y)
  2328. yend = max_clip_y;
  2329.     // test for horizontal clipping
  2330. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2331. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2332. (x2 < min_clip_x) || (x2 > max_clip_x))
  2333. {
  2334.     // clip version
  2335. // point screen ptr to starting line
  2336. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2337.     // point zbuffer to starting line
  2338.     z_ptr = zbuffer + (ystart * zpitch);
  2339. for (yi = ystart; yi < yend; yi++)
  2340. {
  2341. // compute span endpoints
  2342. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2343. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2344. // compute starting points for u,v,w interpolants
  2345. ui = ul + FIXP16_ROUND_UP;
  2346. vi = vl + FIXP16_ROUND_UP;
  2347. wi = wl + FIXP16_ROUND_UP;
  2348. zi = zl + FIXP16_ROUND_UP;
  2349.         si = sl + FIXP16_ROUND_UP;
  2350. ti = tl + FIXP16_ROUND_UP;
  2351. // compute u,v interpolants
  2352. if ((dx = (xend - xstart))>0)
  2353. {
  2354. du = (ur - ul)/dx;
  2355. dv = (vr - vl)/dx;
  2356. dw = (wr - wl)/dx;
  2357. dz = (zr - zl)/dx;
  2358. ds = (sr - sl)/dx;
  2359. dt = (tr - tl)/dx;
  2360. } // end if
  2361. else
  2362. {
  2363. du = (ur - ul);
  2364. dv = (vr - vl);
  2365. dw = (wr - wl);
  2366. dz = (zr - zl);
  2367. ds = (sr - sl);
  2368. dt = (tr - tl);
  2369. } // end else
  2370. ///////////////////////////////////////////////////////////////////////
  2371. // test for x clipping, LHS
  2372. if (xstart < min_clip_x)
  2373. {
  2374. // compute x overlap
  2375. dx = min_clip_x - xstart;
  2376. // slide interpolants over
  2377. ui+=dx*du;
  2378. vi+=dx*dv;
  2379. wi+=dx*dw;
  2380. zi+=dx*dz;
  2381. si+=dx*ds;
  2382. ti+=dx*dt;
  2383. // reset vars
  2384. xstart = min_clip_x;
  2385. } // end if
  2386. // test for x clipping RHS
  2387. if (xend > max_clip_x)
  2388. xend = max_clip_x;
  2389. ///////////////////////////////////////////////////////////////////////
  2390. // draw span
  2391. for (xi=xstart; xi < xend; xi++)
  2392. {
  2393. // write textel assume 5.6.5
  2394.             // write thru z buffer always
  2395.     // get textel first
  2396.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  2397.             // extract rgb components
  2398.             r_textel  = ((textel >> 11)       ); 
  2399.             g_textel  = ((textel >> 5)  & 0x3f); 
  2400.             b_textel =   (textel        & 0x1f);
  2401.             // modulate textel with gouraud shading
  2402.             r_textel*=ui; 
  2403.             g_textel*=vi;
  2404.             b_textel*=wi;
  2405.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  2406.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  2407.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  2408.             // and they all cancel out for the most part, but we will need logical anding, we will do
  2409.             // it later when we optimize more...
  2410.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  2411.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  2412.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  2413.             // update z-buffer
  2414.             z_ptr[xi] = zi;   
  2415. // interpolate u,v
  2416. ui+=du;
  2417. vi+=dv;
  2418. wi+=dw;
  2419. zi+=dz;
  2420. si+=ds;
  2421. ti+=dt;
  2422. } // end for xi
  2423. // interpolate u,v,w,x along right and left edge
  2424. xl+=dxdyl;
  2425. ul+=dudyl;
  2426. vl+=dvdyl;
  2427. wl+=dwdyl;
  2428. zl+=dzdyl;
  2429. sl+=dsdyl;
  2430. tl+=dtdyl;
  2431. xr+=dxdyr;
  2432. ur+=dudyr;
  2433. vr+=dvdyr;
  2434. wr+=dwdyr;
  2435. zr+=dzdyr;
  2436.  
  2437. sr+=dsdyr;
  2438. tr+=dtdyr;
  2439. // advance screen ptr
  2440. screen_ptr+=mem_pitch;
  2441.         // advance zbuffer ptr
  2442.         z_ptr+=zpitch;
  2443. } // end for y
  2444. } // end if clip
  2445. else
  2446. {
  2447. // non-clip version
  2448. // point screen ptr to starting line
  2449. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2450.     // point zbuffer to starting line
  2451.     z_ptr = zbuffer + (ystart * zpitch);
  2452. for (yi = ystart; yi < yend; yi++)
  2453. {
  2454. // compute span endpoints
  2455. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2456. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);