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

游戏

开发平台:

Visual C++

  1. // T3DLIB12.CPP - rasterizers that support textures with transparent pixels
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3. #define DEBUG_ON
  4. #define WIN32_LEAN_AND_MEAN  
  5. #include <windows.h>   // include important windows stuff
  6. #include <windowsx.h> 
  7. #include <mmsystem.h>
  8. #include <objbase.h>
  9. #include <iostream.h> // include important C/C++ stuff
  10. #include <conio.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include <memory.h>
  14. #include <string.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20. #include <direct.h>
  21. #include <wchar.h>
  22. #include <limits.h>
  23. #include <float.h>
  24. #include <search.h>
  25. #include <ddraw.h>      // needed for defs in T3DLIB1.H 
  26. #include "T3DLIB1.H"
  27. #include "T3DLIB4.H"
  28. #include "T3DLIB5.H"
  29. #include "T3DLIB6.H"
  30. #include "T3DLIB7.H"
  31. #include "T3DLIB8.H"
  32. #include "T3DLIB9.H"
  33. #include "T3DLIB10.H"
  34. #include "T3DLIB11.H"
  35. #include "T3DLIB12.H"
  36. // DEFINES //////////////////////////////////////////////////////////////////
  37. // GLOBALS //////////////////////////////////////////////////////////////////
  38. // FUNCTIONS ////////////////////////////////////////////////////////////////
  39. void Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_3(RENDERCONTEXTV1_PTR rc)
  40. {
  41. // this function renders the rendering list, it's based on the new
  42. // rendering context data structure which is container for everything
  43. // we need to consider when rendering, z, 1/z buffering, alpha, mipmapping,
  44. // perspective, bilerp, etc. the function is basically a merge of all the functions
  45. // we have written thus far, so its rather long, but better than having 
  46. // 20-30 rendering functions for all possible permutations!
  47. // this new version _3 supports the new RENDER_ATTR_WRITETHRUZBUFFER 
  48. // functionality in a very limited manner, it supports mip mapping in general
  49. // and only supports the following types:
  50. // constant shaded, flat shaded, gouraud shaded 
  51. // affine only: constant textured, flat textured, and gouraud textured
  52. // when not using the RENDER_ATTR_WRITETHRUZBUFFER support, the 
  53. // function is identical to the previous version
  54. // additionally, this function supports alpha blended constant textures
  55. // and any texture that is constant shaded with alpha with have support for 
  56. // transparent pixels, that is any pixel that has RGB value (0,0,0) in the
  57. // texture will not be rendered, the transparent rasterizers with alpha support
  58. // are for the constant shader, and textured shader, with nozbuffer, zbuffer, and 
  59. // zbuffer writethru
  60. POLYF4DV2 face; // temp face used to render polygon
  61. int alpha;      // alpha of the face
  62. // we need to try and separate as much conditional logic as possible
  63. // at the beginning of the function, so we can minimize it inline during
  64. // the traversal of the polygon list, let's start by subclassing which
  65. // kind of rendering we are doing none, z buffered, or 1/z buffered
  66.                                       
  67. if (rc->attr & RENDER_ATTR_NOBUFFER) ////////////////////////////////////
  68. {
  69. // no buffering at all
  70. // at this point, all we have is a list of polygons and it's time
  71. // to draw them
  72. for (int poly=0; poly < rc->rend_list->num_polys; poly++)
  73.     {
  74.     // render this polygon if and only if it's not clipped, not culled,
  75.     // active, and visible, note however the concecpt of "backface" is 
  76.     // irrelevant in a wire frame engine though
  77.     if (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  78.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  79.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  80.        continue; // move onto next poly
  81.     // test for alpha override
  82.     if (rc->alpha_override>= 0)
  83.        {
  84.        // set alpha to override value
  85.        alpha = rc->alpha_override;
  86.        }  // end if 
  87.     else
  88.         {
  89.         // extract alpha (even if there isn't any)
  90.         alpha = ((rc->rend_list->poly_ptrs[poly]->color & 0xff000000) >> 24);
  91.         } // end else
  92.     // need to test for textured first, since a textured poly can either
  93.     // be emissive, or flat shaded, hence we need to call different
  94.     // rasterizers    
  95.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  96.        {
  97.        // set the vertices
  98.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  99.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  100.        face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  101.        face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
  102.        face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
  103.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  104.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  105.        face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  106.        face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
  107.        face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
  108.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  109.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  110.        face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  111.        face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
  112.        face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
  113.        // test if this is a mipmapped polygon?
  114.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
  115.           {
  116.           // determine if mipmapping is desired at all globally
  117.           if (rc->attr & RENDER_ATTR_MIPMAP)
  118.              {
  119.              // determine mip level for this polygon
  120.              // first determine how many miplevels there are in mipchain for this polygon
  121.              int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
  122.              // now based on the requested linear miplevel fall off distance, cut
  123.              // the viewdistance into segments, determine what segment polygon is
  124.              // in and select mip level -- simple! later you might want something more
  125.              // robust, also note I only use a single vertex, you might want to find the average
  126.              // since for long walls perpendicular to view direction this might causing mip
  127.              // popping mid surface
  128.              int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
  129.           
  130.              // clamp miplevel
  131.              if (miplevel > tmiplevels) miplevel = tmiplevels;
  132.              // based on miplevel select proper texture
  133.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
  134.              // now we must divide each texture coordinate by 2 per miplevel
  135.              for (int ts = 0; ts < miplevel; ts++)
  136.                  {
  137.                  face.tvlist[0].u0*=.5;
  138.                  face.tvlist[0].v0*=.5;
  139.                  face.tvlist[1].u0*=.5;
  140.                  face.tvlist[1].v0*=.5;
  141.                  face.tvlist[2].u0*=.5;
  142.                  face.tvlist[2].v0*=.5;
  143.                 } // end for
  144.              } // end if mipmmaping enabled globally
  145.           else // mipmapping not selected globally
  146.              {
  147.              // in this case the polygon IS mipmapped, but the caller has requested NO
  148.              // mipmapping, so we will support this by selecting mip level 0 since the
  149.              // texture pointer is pointing to a mip chain regardless
  150.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
  151.  
  152.              // note: texture coordinate manipulation is unneeded
  153.              } // end else
  154.           } // end if
  155.        else
  156.           {
  157.           // assign the texture without change
  158.           face.texture = rc->rend_list->poly_ptrs[poly]->texture;
  159.           } // end if
  160.        
  161.        // is this a plain emissive texture?
  162.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  163.           {
  164.           // draw the textured triangle as emissive
  165.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  166.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  167.              {
  168.              // alpha version
  169.              
  170.              // which texture mapper?
  171.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  172.                 {
  173.                 // redo with transparency
  174.                 Draw_Textured_Triangle_Alpha16_2(&face, rc->video_buffer, rc->lpitch, alpha);
  175.                 } // end if
  176.              else
  177.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  178.                 {
  179.                 // not supported yet!
  180.                 // redo with transparency
  181.                 Draw_Textured_Triangle_Alpha16_2(&face, rc->video_buffer, rc->lpitch, alpha);
  182.                 } // end if
  183.              else
  184.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  185.                 {
  186.                 // not supported yet
  187.                 // redo with transparency
  188.                 Draw_Textured_Triangle_Alpha16_2(&face, rc->video_buffer, rc->lpitch, alpha);
  189.                 } // end if
  190.              else
  191.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  192.                 {
  193.                 // test z distance again perspective transition gate
  194.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  195.                     {
  196.                     // default back to affine
  197.                     // redo with transparency
  198.                     Draw_Textured_Triangle_Alpha16_2(&face, rc->video_buffer, rc->lpitch, alpha);
  199.                     } // end if
  200.                 else
  201.                     {
  202.                     // use perspective linear
  203.                     // not supported yet
  204.                     // redo with transparency
  205.                     Draw_Textured_Triangle_Alpha16_2(&face, rc->video_buffer, rc->lpitch, alpha);
  206.                     } // end if
  207.                  } // end if
  208.              } // end if
  209.           else
  210.              {
  211.              // non alpha
  212.              // which texture mapper?
  213.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  214.                 {
  215.                 // use bilerp?
  216.                 if (rc->attr & RENDER_ATTR_BILERP)
  217.                    Draw_Textured_Bilerp_Triangle_16(&face, rc->video_buffer, rc->lpitch);               
  218.                 else
  219.                    Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
  220.                 } // end if
  221.              else
  222.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  223.                 {
  224.                 // not supported yet
  225.                 Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
  226.                 } // end if
  227.              else
  228.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  229.                 {
  230.                 // not supported yet
  231.                 Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
  232.                 } // end if
  233.              else
  234.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  235.                 {
  236.                 // test z distance again perspective transition gate
  237.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  238.                     {
  239.                     // default back to affine
  240.                     Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
  241.                     } // end if
  242.                 else
  243.                     {
  244.                     // use perspective linear
  245.                     // not supported yet
  246.                     Draw_Textured_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
  247.                     } // end if
  248.                 } // end if
  249.              } // end if
  250.           } // end if
  251.        else
  252.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
  253.           {
  254.           // draw as flat shaded
  255.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  256.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  257.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  258.              {
  259.              // alpha version
  260.              
  261.              // which texture mapper?
  262.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  263.                 {
  264.                 Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  265.                 } // end if
  266.              else
  267.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  268.                 {
  269.                 // not supported yet!
  270.                 Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  271.                 } // end if
  272.              else
  273.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  274.                 {
  275.                 // not supported yet
  276.                 Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  277.                 } // end if
  278.              else
  279.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  280.                 {
  281.                 // test z distance again perspective transition gate
  282.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  283.                     {
  284.                     // default back to affine
  285.                     Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  286.                     } // end if
  287.                 else
  288.                     {
  289.                     // use perspective linear
  290.                     // not supported yet
  291.                     Draw_Textured_TriangleFS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  292.                     } // end if
  293.                  } // end if
  294.              } // end if
  295.           else
  296.              {
  297.              // non alpha
  298.              // which texture mapper?
  299.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  300.                 {
  301.                 Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
  302.                 } // end if
  303.              else
  304.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  305.                 {
  306.                 // not supported yet
  307.                 Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
  308.                 } // end if
  309.              else
  310.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  311.                 {
  312.                 // not supported yet
  313.                 Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
  314.                 } // end if
  315.              else
  316.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  317.                 {
  318.                 // test z distance again perspective transition gate
  319.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  320.                     {
  321.                     // default back to affine
  322.                     Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
  323.                     } // end if
  324.                 else
  325.                     {
  326.                     // use perspective linear
  327.                     // not supported yet
  328.                     Draw_Textured_TriangleFS2_16(&face, rc->video_buffer, rc->lpitch);
  329.                     } // end if
  330.                 } // end if
  331.              } // end if
  332.           } // end else
  333.        else
  334.           {
  335.           // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  336.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  337.           face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  338.           face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  339.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  340.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  341.              {
  342.              // alpha version
  343.              
  344.              // which texture mapper?
  345.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  346.                 {
  347.                 Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  348.                 } // end if
  349.              else
  350.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  351.                 {
  352.                 // not supported yet!
  353.                 Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  354.                 } // end if
  355.              else
  356.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  357.                 {
  358.                 // not supported yet
  359.                 Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  360.                 } // end if
  361.              else
  362.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  363.                 {
  364.                 // test z distance again perspective transition gate
  365.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  366.                     {
  367.                     // default back to affine
  368.                     Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  369.                     } // end if
  370.                 else
  371.                     {
  372.                     // use perspective linear
  373.                     // not supported yet
  374.                     Draw_Textured_TriangleGS_Alpha16(&face, rc->video_buffer, rc->lpitch, alpha);
  375.                     } // end if
  376.                  } // end if
  377.              } // end if
  378.           else
  379.              {
  380.              // non alpha
  381.              // which texture mapper?
  382.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  383.                 {
  384.                 Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
  385.                 } // end if
  386.              else
  387.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  388.                 {
  389.                 // not supported yet
  390.                 Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
  391.                 } // end if
  392.              else
  393.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  394.                 {
  395.                 // not supported yet
  396.                 Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
  397.                 } // end if
  398.              else
  399.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  400.                 {
  401.                 // test z distance again perspective transition gate
  402.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  403.                     {
  404.                     // default back to affine
  405.                     Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
  406.                     } // end if
  407.                 else
  408.                     {
  409.                     // use perspective linear
  410.                     // not supported yet
  411.                     Draw_Textured_TriangleGS_16(&face, rc->video_buffer, rc->lpitch);
  412.                     } // end if
  413.                 } // end if
  414.              } // end if
  415.           } // end else
  416.        } // end if      
  417.     else
  418.     if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  419.         (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  420.        {
  421.        // draw as constant shaded
  422.        face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  423.        
  424.        // set the vertices
  425.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  426.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  427.        face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  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.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  432.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  433.        face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  434.        // draw the triangle with basic flat rasterizer
  435.        // test for transparent
  436.        if ((rc->attr & RENDER_ATTR_ALPHA) &&
  437.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  438.           {
  439.           // redo with transparency
  440.           Draw_Triangle_2D_Alpha16(&face, rc->video_buffer, rc->lpitch,alpha);
  441.           } // end if
  442.        else
  443.           {
  444.           Draw_Triangle_2D3_16(&face, rc->video_buffer, rc->lpitch);
  445.           } // end if
  446.                           
  447.        } // end if                    
  448.     else
  449.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  450.        {
  451.         // {andre take advantage of the data structures later..}
  452.         // set the vertices
  453.         face.tvlist[0].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  454.         face.tvlist[0].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  455.         face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  456.         face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  457.         face.tvlist[1].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  458.         face.tvlist[1].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  459.         face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  460.         face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  461.         face.tvlist[2].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  462.         face.tvlist[2].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  463.         face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  464.         face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  465.     // draw the gouraud shaded triangle
  466.         // test for transparent
  467.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  468.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  469.            {
  470.            Draw_Gouraud_Triangle_Alpha16(&face, rc->video_buffer, rc->lpitch,alpha);
  471.            } // end if
  472.         else
  473.            {
  474.            Draw_Gouraud_Triangle2_16(&face, rc->video_buffer, rc->lpitch);
  475.            } // end if
  476.        } // end if gouraud
  477.     } // end for poly
  478. } // end if RENDER_ATTR_NOBUFFER
  479. else
  480. if (rc->attr & RENDER_ATTR_ZBUFFER) ////////////////////////////////////
  481. {
  482. // use the z buffer
  483. // we have is a list of polygons and it's time draw them
  484. for (int poly=0; poly < rc->rend_list->num_polys; poly++)
  485.     {
  486.     // render this polygon if and only if it's not clipped, not culled,
  487.     // active, and visible, note however the concecpt of "backface" is 
  488.     // irrelevant in a wire frame engine though
  489.     if (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  490.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  491.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  492.        continue; // move onto next poly
  493.     // test for alpha override
  494.     if (rc->alpha_override>= 0)
  495.        {
  496.        // set alpha to override value
  497.        alpha = rc->alpha_override;
  498.        }  // end if 
  499.     else
  500.         {
  501.         // extract alpha (even if there isn't any)
  502.         alpha = ((rc->rend_list->poly_ptrs[poly]->color & 0xff000000) >> 24);
  503.         } // end else
  504.     // need to test for textured first, since a textured poly can either
  505.     // be emissive, or flat shaded, hence we need to call different
  506.     // rasterizers    
  507.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  508.        {
  509.        // set the vertices
  510.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  511.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  512.        face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  513.        face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
  514.        face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
  515.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  516.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  517.        face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  518.        face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
  519.        face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
  520.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  521.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  522.        face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  523.        face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
  524.        face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
  525.     
  526.        // test if this is a mipmapped polygon?
  527.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
  528.           {
  529.           // determine if mipmapping is desired at all globally
  530.           if (rc->attr & RENDER_ATTR_MIPMAP)
  531.              {
  532.              // determine mip level for this polygon
  533.              // first determine how many miplevels there are in mipchain for this polygon
  534.              int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
  535.              // now based on the requested linear miplevel fall off distance, cut
  536.              // the viewdistance into segments, determine what segment polygon is
  537.              // in and select mip level -- simple! later you might want something more
  538.              // robust, also note I only use a single vertex, you might want to find the average
  539.              // since for long walls perpendicular to view direction this might causing mip
  540.              // popping mid surface
  541.              int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
  542.           
  543.              // clamp miplevel
  544.              if (miplevel > tmiplevels) miplevel = tmiplevels;
  545.              // based on miplevel select proper texture
  546.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
  547.              // now we must divide each texture coordinate by 2 per miplevel
  548.              for (int ts = 0; ts < miplevel; ts++)
  549.                  {
  550.                  face.tvlist[0].u0*=.5;
  551.                  face.tvlist[0].v0*=.5;
  552.                  face.tvlist[1].u0*=.5;
  553.                  face.tvlist[1].v0*=.5;
  554.                  face.tvlist[2].u0*=.5;
  555.                  face.tvlist[2].v0*=.5;
  556.                 } // end for
  557.              } // end if mipmmaping enabled globally
  558.           else // mipmapping not selected globally
  559.              {
  560.              // in this case the polygon IS mipmapped, but the caller has requested NO
  561.              // mipmapping, so we will support this by selecting mip level 0 since the
  562.              // texture pointer is pointing to a mip chain regardless
  563.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
  564.  
  565.              // note: texture coordinate manipulation is unneeded
  566.              } // end else
  567.           } // end if
  568.        else
  569.           {
  570.           // assign the texture without change
  571.           face.texture = rc->rend_list->poly_ptrs[poly]->texture;
  572.           } // end if
  573.        
  574.        // is this a plain emissive texture?
  575.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  576.           {
  577.           // draw the textured triangle as emissive
  578.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  579.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  580.              {
  581.              // alpha version
  582.              
  583.              // which texture mapper?
  584.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  585.                 {
  586.                 // redo with transparency
  587.                 Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  588.                 } // end if
  589.              else
  590.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  591.                 {
  592.                 // not supported yet!
  593.                 // redo with transparency
  594.                 Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  595.                 } // end if
  596.              else
  597.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  598.                 {
  599.                 // not supported yet
  600.                 // redo with transparency
  601.                 Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  602.                 } // end if
  603.              else
  604.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  605.                 {
  606.                 // test z distance again perspective transition gate
  607.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  608.                     {
  609.                     // default back to affine
  610.                     // redo with transparency
  611.                     Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  612.                     } // end if
  613.                 else
  614.                     {
  615.                     // use perspective linear
  616.                     // not supported yet
  617.                     // redo with transparency
  618.                     Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  619.                     } // end if
  620.                  } // end if
  621.              } // end if
  622.           else
  623.              {
  624.              // non alpha
  625.              // which texture mapper?
  626.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  627.                 {
  628.                 // use bilerp?
  629.                 if (rc->attr & RENDER_ATTR_BILERP)
  630.                    Draw_Textured_Bilerp_TriangleZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);               
  631.                 else
  632.                    Draw_Textured_TriangleZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  633.                 } // end if
  634.              else
  635.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  636.                 {
  637.                 // not supported yet
  638.                 Draw_Textured_TriangleZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  639.                 } // end if
  640.              else
  641.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  642.                 {
  643.                 // not supported yet
  644.                 Draw_Textured_TriangleZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  645.                 } // end if
  646.              else
  647.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  648.                 {
  649.                 // test z distance again perspective transition gate
  650.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  651.                     {
  652.                     // default back to affine
  653.                     Draw_Textured_TriangleZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  654.                     } // end if
  655.                 else
  656.                     {
  657.                     // use perspective linear
  658.                     // not supported yet
  659.                     Draw_Textured_TriangleZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  660.                     } // end if
  661.                 } // end if
  662.              } // end if
  663.           } // end if
  664.        else
  665.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
  666.           {
  667.           // draw as flat shaded
  668.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  669.           // test for transparency
  670.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  671.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  672.              {
  673.              // alpha version
  674.              // which texture mapper?
  675.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  676.                 {
  677.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  678.                 } // end if
  679.              else
  680.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  681.                 {
  682.                 // not supported yet
  683.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  684.                 } // end if
  685.              else
  686.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  687.                 {
  688.                 // not supported yet
  689.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  690.                 } // end if
  691.              else
  692.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  693.                 {
  694.                 // test z distance again perspective transition gate
  695.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  696.                     {
  697.                     // default back to affine
  698.                     Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  699.                     } // end if
  700.                 else
  701.                     {
  702.                     // use perspective linear
  703.                     // not supported yet
  704.                     Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  705.                     } // end if
  706.                  } // end if
  707.              } // end if
  708.           else
  709.              {
  710.              // non alpha
  711.              // which texture mapper?
  712.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  713.                 {
  714.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  715.                 } // end if
  716.              else
  717.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  718.                 {
  719.                 // not supported yet
  720.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  721.                 } // end if
  722.              else
  723.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  724.                 {
  725.                 // not supported yet
  726.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  727.                 } // end if
  728.              else
  729.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  730.                 {
  731.                 // test z distance again perspective transition gate
  732.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  733.                     {
  734.                     // default back to affine
  735.                     Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  736.                     } // end if
  737.                 else
  738.                     {
  739.                     // use perspective linear
  740.                     // not supported yet
  741.                     Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  742.                     } // end if
  743.                  } // end if
  744.              } // end if
  745.           } // end else if
  746.       else
  747.          { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  748.           // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  749.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  750.           face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  751.           face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  752.          // test for transparency
  753.          if ((rc->attr & RENDER_ATTR_ALPHA) &&
  754.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  755.              {
  756.              // alpha version
  757.              // which texture mapper?
  758.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  759.                 {
  760.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  761.                 } // end if
  762.              else
  763.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  764.                 {
  765.                 // not supported yet :)
  766.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  767.                 } // end if
  768.              else
  769.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  770.                 {
  771.                 // not supported yet :)
  772.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  773.                 } // end if
  774.              else
  775.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  776.                 {
  777.                 // test z distance again perspective transition gate
  778.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  779.                     {
  780.                     // default back to affine
  781.                     Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  782.                     } // end if
  783.                 else
  784.                     {
  785.                     // use perspective linear
  786.                     // not supported yet :)
  787.                     Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  788.                     } // end if
  789.                  } // end if
  790.              } // end if
  791.           else
  792.              {
  793.              // non alpha
  794.              // which texture mapper?
  795.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  796.                 {
  797.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  798.                 } // end if
  799.              else
  800.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  801.                 {
  802.                 // not supported yet :)
  803.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  804.                 } // end if
  805.              else
  806.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  807.                 {
  808.                 // not supported yet :)
  809.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  810.                 } // end if
  811.              else
  812.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  813.                 {
  814.                 // test z distance again perspective transition gate
  815.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  816.                     {
  817.                     // default back to affine
  818.                     Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  819.                     } // end if
  820.                 else
  821.                     {
  822.                     // use perspective linear
  823.                     // not supported yet :)
  824.                     Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  825.                     } // end if
  826.                  } // end if
  827.              } // end if
  828.          } // end else
  829.        } // end if      
  830.     else
  831.     if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  832.         (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  833.        {
  834.        // draw as constant shaded
  835.        face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  836.        
  837.        // set the vertices
  838.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  839.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  840.        face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  841.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  842.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  843.        face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  844.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  845.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  846.        face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  847.        // draw the triangle with basic flat rasterizer
  848.        // test for transparency
  849.        if ((rc->attr & RENDER_ATTR_ALPHA) &&
  850.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  851.           {
  852.           // alpha version
  853.           // redo with transparency
  854.           Draw_Triangle_2DZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  855.           } // end if
  856.        else
  857.           {
  858.           // non alpha version
  859.           Draw_Triangle_2DZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  860.           }  // end if
  861.        } // end if
  862.     else
  863.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  864.        {
  865.         // {andre take advantage of the data structures later..}
  866.         // set the vertices
  867.         face.tvlist[0].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  868.         face.tvlist[0].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  869.         face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  870.         face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  871.         face.tvlist[1].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  872.         face.tvlist[1].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  873.         face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  874.         face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  875.         face.tvlist[2].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  876.         face.tvlist[2].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  877.         face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  878.         face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  879.     // draw the gouraud shaded triangle
  880.         // test for transparency
  881.         if ((rc->attr & RENDER_ATTR_ALPHA) &&
  882.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  883.            {
  884.            // alpha version
  885.            Draw_Gouraud_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  886.            } // end if
  887.         else
  888.            { 
  889.            // non alpha
  890.            Draw_Gouraud_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  891.            } // end if
  892.        } // end if gouraud
  893.     } // end for poly
  894. } // end if RENDER_ATTR_ZBUFFER
  895. else
  896. if (rc->attr & RENDER_ATTR_INVZBUFFER) ////////////////////////////////////
  897. {
  898. // use the inverse z buffer
  899. // we have is a list of polygons and it's time draw them
  900. for (int poly=0; poly < rc->rend_list->num_polys; poly++)
  901.     {
  902.     // render this polygon if and only if it's not clipped, not culled,
  903.     // active, and visible, note however the concecpt of "backface" is 
  904.     // irrelevant in a wire frame engine though
  905.     if (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  906.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  907.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  908.        continue; // move onto next poly
  909.     // test for alpha override
  910.     if (rc->alpha_override>= 0)
  911.        {
  912.        // set alpha to override value
  913.        alpha = rc->alpha_override;
  914.        }  // end if 
  915.     else
  916.        {
  917.        // extract alpha (even if there isn't any)
  918.        alpha = ((rc->rend_list->poly_ptrs[poly]->color & 0xff000000) >> 24);
  919.        } // end else
  920.     // need to test for textured first, since a textured poly can either
  921.     // be emissive, or flat shaded, hence we need to call different
  922.     // rasterizers    
  923.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  924.        {
  925.        // set the vertices
  926.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  927.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  928.        face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  929.        face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
  930.        face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
  931.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  932.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  933.        face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  934.        face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
  935.        face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
  936.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  937.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  938.        face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  939.        face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
  940.        face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
  941.     
  942.     
  943.        // test if this is a mipmapped polygon?
  944.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
  945.           {
  946.           // determine if mipmapping is desired at all globally
  947.           if (rc->attr & RENDER_ATTR_MIPMAP)
  948.              {
  949.              // determine mip level for this polygon
  950.              // first determine how many miplevels there are in mipchain for this polygon
  951.              int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
  952.              // now based on the requested linear miplevel fall off distance, cut
  953.              // the viewdistance into segments, determine what segment polygon is
  954.              // in and select mip level -- simple! later you might want something more
  955.              // robust, also note I only use a single vertex, you might want to find the average
  956.              // since for long walls perpendicular to view direction this might causing mip
  957.              // popping mid surface
  958.              int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
  959.           
  960.              // clamp miplevel
  961.              if (miplevel > tmiplevels) miplevel = tmiplevels;
  962.              // based on miplevel select proper texture
  963.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
  964.              // now we must divide each texture coordinate by 2 per miplevel
  965.              for (int ts = 0; ts < miplevel; ts++)
  966.                  {
  967.                  face.tvlist[0].u0*=.5;
  968.                  face.tvlist[0].v0*=.5;
  969.                  face.tvlist[1].u0*=.5;
  970.                  face.tvlist[1].v0*=.5;
  971.                  face.tvlist[2].u0*=.5;
  972.                  face.tvlist[2].v0*=.5;
  973.                 } // end for
  974.              } // end if mipmmaping enabled globally
  975.           else // mipmapping not selected globally
  976.              {
  977.              // in this case the polygon IS mipmapped, but the caller has requested NO
  978.              // mipmapping, so we will support this by selecting mip level 0 since the
  979.              // texture pointer is pointing to a mip chain regardless
  980.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
  981.  
  982.              // note: texture coordinate manipulation is unneeded
  983.              } // end else
  984.           } // end if
  985.        else
  986.           {
  987.           // assign the texture without change
  988.           face.texture = rc->rend_list->poly_ptrs[poly]->texture;
  989.           } // end if
  990.               
  991.        // is this a plain emissive texture?
  992.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  993.           {
  994.           // draw the textured triangle as emissive
  995.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  996.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  997.              {
  998.              // alpha version
  999.              
  1000.              // which texture mapper?
  1001.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1002.                 {
  1003.                 Draw_Textured_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1004.                 } // end if
  1005.              else
  1006.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1007.                 {
  1008.                 Draw_Textured_Perspective_Triangle_INVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1009.                 } // end if
  1010.              else
  1011.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1012.                 {
  1013.                 Draw_Textured_PerspectiveLP_Triangle_INVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1014.                 } // end if
  1015.              else
  1016.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1017.                 {
  1018.                 // test z distance again perspective transition gate
  1019.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1020.                     {
  1021.                     // default back to affine
  1022.                     Draw_Textured_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1023.                     } // end if
  1024.                 else
  1025.                     {
  1026.                     // use perspective linear
  1027.                     Draw_Textured_PerspectiveLP_Triangle_INVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1028.                     } // end if
  1029.                  } // end if
  1030.              } // end if
  1031.           else
  1032.              {
  1033.              // non alpha
  1034.              // which texture mapper?
  1035.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1036.                 {
  1037.                 // use bilerp?
  1038.                 if (rc->attr & RENDER_ATTR_BILERP)
  1039.                     Draw_Textured_Bilerp_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);             
  1040.                 else
  1041.                     Draw_Textured_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1042.                 } // end if
  1043.              else
  1044.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1045.                 {
  1046.                 Draw_Textured_Perspective_Triangle_INVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1047.                 } // end if
  1048.              else
  1049.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1050.                 {
  1051.                 Draw_Textured_PerspectiveLP_Triangle_INVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1052.                 } // end if
  1053.              else
  1054.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1055.                 {
  1056.                 // test z distance again perspective transition gate
  1057.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1058.                     {
  1059.                     // default back to affine
  1060.                     Draw_Textured_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1061.                     } // end if
  1062.                 else
  1063.                     {
  1064.                     // use perspective linear
  1065.                     Draw_Textured_PerspectiveLP_Triangle_INVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1066.                     } // end if
  1067.                 } // end if
  1068.              } // end if
  1069.           } // end if
  1070.        else
  1071.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
  1072.           {
  1073.           // draw as flat shaded
  1074.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1075.           // test for transparency
  1076.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1077.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1078.              {
  1079.              // alpha version
  1080.              // which texture mapper?
  1081.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1082.                 {
  1083.                 Draw_Textured_TriangleFSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1084.                 } // end if
  1085.              else
  1086.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1087.                 {
  1088.                 Draw_Textured_Perspective_Triangle_FSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1089.                 } // end if
  1090.              else
  1091.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1092.                 {
  1093.                 Draw_Textured_PerspectiveLP_Triangle_FSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1094.                 } // end if
  1095.              else
  1096.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1097.                 {
  1098.                 // test z distance again perspective transition gate
  1099.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1100.                     {
  1101.                     // default back to affine
  1102.                     Draw_Textured_TriangleFSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1103.                     } // end if
  1104.                 else
  1105.                     {
  1106.                     // use perspective linear
  1107.                     Draw_Textured_PerspectiveLP_Triangle_FSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1108.                     } // end if
  1109.                  } // end if
  1110.              } // end if
  1111.           else
  1112.              {
  1113.              // non alpha
  1114.              // which texture mapper?
  1115.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1116.                 {
  1117.                 Draw_Textured_TriangleFSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1118.                 } // end if
  1119.              else
  1120.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1121.                 {
  1122.                 Draw_Textured_Perspective_Triangle_FSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1123.                 } // end if
  1124.              else
  1125.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1126.                 {
  1127.                 Draw_Textured_PerspectiveLP_Triangle_FSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1128.                 } // end if
  1129.              else
  1130.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1131.                 {
  1132.                 // test z distance again perspective transition gate
  1133.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1134.                     {
  1135.                     // default back to affine
  1136.                     Draw_Textured_TriangleFSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1137.                     } // end if
  1138.                 else
  1139.                     {
  1140.                     // use perspective linear
  1141.                     Draw_Textured_PerspectiveLP_Triangle_FSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1142.                     } // end if
  1143.                  } // end if
  1144.              } // end if
  1145.           } // end else if
  1146.       else
  1147.          { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  1148.           // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  1149.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1150.           face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  1151.           face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  1152.          // test for transparency
  1153.          if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1154.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1155.              {
  1156.              // alpha version
  1157.              // which texture mapper?
  1158.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1159.                 {
  1160.                 Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1161.                 } // end if
  1162.              else
  1163.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1164.                 {
  1165.                 // not supported yet :)
  1166.                 Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1167.                 } // end if
  1168.              else
  1169.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1170.                 {
  1171.                 // not supported yet :)
  1172.                 Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1173.                 } // end if
  1174.              else
  1175.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1176.                 {
  1177.                 // test z distance again perspective transition gate
  1178.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1179.                     {
  1180.                     // default back to affine
  1181.                     Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1182.                     } // end if
  1183.                 else
  1184.                     {
  1185.                     // use perspective linear
  1186.                     // not supported yet :)
  1187.                     Draw_Textured_TriangleGSINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1188.                     } // end if
  1189.                  } // end if
  1190.              } // end if
  1191.           else
  1192.              {
  1193.              // non alpha
  1194.              // which texture mapper?
  1195.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1196.                 {
  1197.                 Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1198.                 } // end if
  1199.              else
  1200.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1201.                 {
  1202.                 // not supported yet :)
  1203.                 Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1204.                 } // end if
  1205.              else
  1206.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1207.                 {
  1208.                 // not supported yet :)
  1209.                 Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1210.                 } // end if
  1211.              else
  1212.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1213.                 {
  1214.                 // test z distance again perspective transition gate
  1215.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1216.                     {
  1217.                     // default back to affine
  1218.                     Draw_Textured_TriangleFSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1219.                     } // end if
  1220.                 else
  1221.                     {
  1222.                     // use perspective linear
  1223.                     // not supported yet :)
  1224.                     Draw_Textured_TriangleGSINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1225.                     } // end if
  1226.                  } // end if
  1227.              } // end if
  1228.          } // end else
  1229.        } // end if      
  1230.     else
  1231.     if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  1232.         (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  1233.        {
  1234.        // draw as constant shaded
  1235.        face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1236.        
  1237.        // set the vertices
  1238.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  1239.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  1240.        face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  1241.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  1242.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  1243.        face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  1244.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  1245.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  1246.        face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  1247.        // draw the triangle with basic flat rasterizer
  1248.        // test for transparency
  1249.        if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1250.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1251.           {
  1252.           // alpha version
  1253.           Draw_Triangle_2DINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  1254.           } // end if
  1255.        else
  1256.           {
  1257.           // non alpha version
  1258.           Draw_Triangle_2DINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1259.           }  // end if
  1260.        } // end if
  1261.     else
  1262.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  1263.        {
  1264.         // {andre take advantage of the data structures later..}
  1265.         // set the vertices
  1266.         face.tvlist[0].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  1267.         face.tvlist[0].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  1268.         face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  1269.         face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1270.         face.tvlist[1].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  1271.         face.tvlist[1].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  1272.         face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  1273.         face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  1274.         face.tvlist[2].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  1275.         face.tvlist[2].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  1276.         face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  1277.         face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  1278.     // draw the gouraud shaded triangle
  1279.         // test for transparency
  1280.         if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1281.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1282.            {
  1283.            // alpha version
  1284.            Draw_Gouraud_TriangleINVZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  1285.            } // end if
  1286.         else
  1287.            { 
  1288.            // non alpha
  1289.            Draw_Gouraud_TriangleINVZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1290.            } // end if
  1291.        } // end if gouraud
  1292.     } // end for poly
  1293. } // end if RENDER_ATTR_INVZBUFFER
  1294. else
  1295. if (rc->attr & RENDER_ATTR_WRITETHRUZBUFFER) ////////////////////////////////////
  1296. {
  1297. // use the write thru z buffer
  1298. // we have is a list of polygons and it's time draw them
  1299. for (int poly=0; poly < rc->rend_list->num_polys; poly++)
  1300.     {
  1301.     // render this polygon if and only if it's not clipped, not culled,
  1302.     // active, and visible, note however the concecpt of "backface" is 
  1303.     // irrelevant in a wire frame engine though
  1304.     if (!(rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  1305.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  1306.          (rc->rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  1307.        continue; // move onto next poly
  1308.     // test for alpha override
  1309.     if (rc->alpha_override>= 0)
  1310.        {
  1311.        // set alpha to override value
  1312.        alpha = rc->alpha_override;
  1313.        }  // end if 
  1314.     else
  1315.         {
  1316.         // extract alpha (even if there isn't any)
  1317.         alpha = ((rc->rend_list->poly_ptrs[poly]->color & 0xff000000) >> 24);
  1318.         } // end else
  1319.     // need to test for textured first, since a textured poly can either
  1320.     // be emissive, or flat shaded, hence we need to call different
  1321.     // rasterizers    
  1322.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  1323.        {
  1324.        // set the vertices
  1325.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  1326.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  1327.        face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  1328.        face.tvlist[0].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].u0;
  1329.        face.tvlist[0].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].v0;
  1330.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  1331.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  1332.        face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  1333.        face.tvlist[1].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].u0;
  1334.        face.tvlist[1].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].v0;
  1335.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  1336.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  1337.        face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  1338.        face.tvlist[2].u0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].u0;
  1339.        face.tvlist[2].v0 = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].v0;
  1340.     
  1341.        // test if this is a mipmapped polygon?
  1342.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_MIPMAP)
  1343.           {
  1344.           // determine if mipmapping is desired at all globally
  1345.           if (rc->attr & RENDER_ATTR_MIPMAP)
  1346.              {
  1347.              // determine mip level for this polygon
  1348.              // first determine how many miplevels there are in mipchain for this polygon
  1349.              int tmiplevels = logbase2ofx[((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0]->width];
  1350.              // now based on the requested linear miplevel fall off distance, cut
  1351.              // the viewdistance into segments, determine what segment polygon is
  1352.              // in and select mip level -- simple! later you might want something more
  1353.              // robust, also note I only use a single vertex, you might want to find the average
  1354.              // since for long walls perpendicular to view direction this might causing mip
  1355.              // popping mid surface
  1356.              int miplevel = (tmiplevels * rc->rend_list->poly_ptrs[poly]->tvlist[0].z / rc->mip_dist);
  1357.           
  1358.              // clamp miplevel
  1359.              if (miplevel > tmiplevels) miplevel = tmiplevels;
  1360.              // based on miplevel select proper texture
  1361.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[miplevel];
  1362.              // now we must divide each texture coordinate by 2 per miplevel
  1363.              for (int ts = 0; ts < miplevel; ts++)
  1364.                  {
  1365.                  face.tvlist[0].u0*=.5;
  1366.                  face.tvlist[0].v0*=.5;
  1367.                  face.tvlist[1].u0*=.5;
  1368.                  face.tvlist[1].v0*=.5;
  1369.                  face.tvlist[2].u0*=.5;
  1370.                  face.tvlist[2].v0*=.5;
  1371.                 } // end for
  1372.              } // end if mipmmaping enabled globally
  1373.           else // mipmapping not selected globally
  1374.              {
  1375.              // in this case the polygon IS mipmapped, but the caller has requested NO
  1376.              // mipmapping, so we will support this by selecting mip level 0 since the
  1377.              // texture pointer is pointing to a mip chain regardless
  1378.              face.texture = ((BITMAP_IMAGE_PTR *)(rc->rend_list->poly_ptrs[poly]->texture))[0];
  1379.  
  1380.              // note: texture coordinate manipulation is unneeded
  1381.              } // end else
  1382.           } // end if
  1383.        else
  1384.           {
  1385.           // assign the texture without change
  1386.           face.texture = rc->rend_list->poly_ptrs[poly]->texture;
  1387.           } // end if
  1388.        
  1389.        // is this a plain emissive texture?
  1390.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  1391.           {
  1392.           // draw the textured triangle as emissive
  1393.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1394.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1395.              {
  1396.              // alpha version
  1397.              
  1398.              // which texture mapper?
  1399.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1400.                 {
  1401.                 // redo with transparency
  1402.                 Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1403.                 } // end if
  1404.              else
  1405.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1406.                 {
  1407.                 // not supported yet!
  1408.                 // redo with transparency
  1409.                 Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1410.                 } // end if
  1411.              else
  1412.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1413.                 {
  1414.                 // not supported yet
  1415.                 // redo with transparency
  1416.                 Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1417.                 } // end if
  1418.              else
  1419.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1420.                 {
  1421.                 // test z distance again perspective transition gate
  1422.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1423.                     {
  1424.                     // default back to affine
  1425.                     // redo with transparency
  1426.                     Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1427.                     } // end if
  1428.                 else
  1429.                     {
  1430.                     // use perspective linear
  1431.                     // not supported yet
  1432.                     // redo with transparency
  1433.                     Draw_Textured_TriangleZB_Alpha16_2(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1434.                     } // end if
  1435.                  } // end if
  1436.              } // end if
  1437.           else
  1438.              {
  1439.              // non alpha
  1440.              // which texture mapper?
  1441.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1442.                 {
  1443.                 // use bilerp?
  1444.                 if (rc->attr & RENDER_ATTR_BILERP)
  1445.                    Draw_Textured_Bilerp_TriangleZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);               
  1446.                 else
  1447.                    Draw_Textured_TriangleWTZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1448.                 } // end if
  1449.              else
  1450.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1451.                 {
  1452.                 // not supported yet
  1453.                 Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1454.                 } // end if
  1455.              else
  1456.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1457.                 {
  1458.                 // not supported yet
  1459.                 Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1460.                 } // end if
  1461.              else
  1462.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1463.                 {
  1464.                 // test z distance again perspective transition gate
  1465.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1466.                     {
  1467.                     // default back to affine
  1468.                     Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1469.                     } // end if
  1470.                 else
  1471.                     {
  1472.                     // use perspective linear
  1473.                     // not supported yet
  1474.                     Draw_Textured_TriangleZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1475.                     } // end if
  1476.                 } // end if
  1477.              } // end if
  1478.           } // end if
  1479.        else
  1480.        if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT)
  1481.           {
  1482.           // draw as flat shaded
  1483.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1484.           // test for transparency
  1485.           if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1486.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1487.              {
  1488.              // alpha version
  1489.              // which texture mapper?
  1490.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1491.                 {
  1492.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1493.                 } // end if
  1494.              else
  1495.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1496.                 {
  1497.                 // not supported yet
  1498.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1499.                 } // end if
  1500.              else
  1501.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1502.                 {
  1503.                 // not supported yet
  1504.                 Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1505.                 } // end if
  1506.              else
  1507.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1508.                 {
  1509.                 // test z distance again perspective transition gate
  1510.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1511.                     {
  1512.                     // default back to affine
  1513.                     Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1514.                     } // end if
  1515.                 else
  1516.                     {
  1517.                     // use perspective linear
  1518.                     // not supported yet
  1519.                     Draw_Textured_TriangleFSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1520.                     } // end if
  1521.                  } // end if
  1522.              } // end if
  1523.           else
  1524.              {
  1525.              // non alpha
  1526.              // which texture mapper?
  1527.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1528.                 {
  1529.                 Draw_Textured_TriangleFSWTZB3_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1530.                 } // end if
  1531.              else
  1532.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1533.                 {
  1534.                 // not supported yet
  1535.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1536.                 } // end if
  1537.              else
  1538.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1539.                 {
  1540.                 // not supported yet
  1541.                 Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1542.                 } // end if
  1543.              else
  1544.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1545.                 {
  1546.                 // test z distance again perspective transition gate
  1547.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1548.                     {
  1549.                     // default back to affine
  1550.                     Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1551.                     } // end if
  1552.                 else
  1553.                     {
  1554.                     // use perspective linear
  1555.                     // not supported yet
  1556.                     Draw_Textured_TriangleFSZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1557.                     } // end if
  1558.                  } // end if
  1559.              } // end if
  1560.           } // end else if
  1561.       else
  1562.          { // POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  1563.           // must be gouraud POLY4DV2_ATTR_SHADE_MODE_GOURAUD
  1564.           face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1565.           face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  1566.           face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  1567.          // test for transparency
  1568.          if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1569.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1570.              {
  1571.              // alpha version
  1572.              // which texture mapper?
  1573.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1574.                 {
  1575.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1576.                 } // end if
  1577.              else
  1578.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1579.                 {
  1580.                 // not supported yet :)
  1581.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1582.                 } // end if
  1583.              else
  1584.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1585.                 {
  1586.                 // not supported yet :)
  1587.                 Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1588.                 } // end if
  1589.              else
  1590.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1591.                 {
  1592.                 // test z distance again perspective transition gate
  1593.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1594.                     {
  1595.                     // default back to affine
  1596.                     Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1597.                     } // end if
  1598.                 else
  1599.                     {
  1600.                     // use perspective linear
  1601.                     // not supported yet :)
  1602.                     Draw_Textured_TriangleGSZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch, alpha);
  1603.                     } // end if
  1604.                  } // end if
  1605.              } // end if
  1606.           else
  1607.              {
  1608.              // non alpha
  1609.              // which texture mapper?
  1610.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE)
  1611.                 {
  1612.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1613.                 } // end if
  1614.              else
  1615.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_CORRECT)
  1616.                 {
  1617.                 // not supported yet :)
  1618.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1619.                 } // end if
  1620.              else
  1621.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_LINEAR)
  1622.                 {
  1623.                 // not supported yet :)
  1624.                 Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1625.                 } // end if
  1626.              else
  1627.              if (rc->attr & RENDER_ATTR_TEXTURE_PERSPECTIVE_HYBRID1)
  1628.                 {
  1629.                 // test z distance again perspective transition gate
  1630.                 if (rc->rend_list->poly_ptrs[poly]->tvlist[0].z > rc-> texture_dist)
  1631.                     {
  1632.                     // default back to affine
  1633.                     Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1634.                     } // end if
  1635.                 else
  1636.                     {
  1637.                     // use perspective linear
  1638.                     // not supported yet :)
  1639.                     Draw_Textured_TriangleGSZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1640.                     } // end if
  1641.                  } // end if
  1642.              } // end if
  1643.          } // end else
  1644.        } // end if      
  1645.     else
  1646.     if ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  1647.         (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  1648.        {
  1649.        // draw as constant shaded
  1650.        face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1651.        
  1652.        // set the vertices
  1653.        face.tvlist[0].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  1654.        face.tvlist[0].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  1655.        face.tvlist[0].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  1656.        face.tvlist[1].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  1657.        face.tvlist[1].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  1658.        face.tvlist[1].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  1659.        face.tvlist[2].x = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  1660.        face.tvlist[2].y = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  1661.        face.tvlist[2].z = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  1662.        // draw the triangle with basic flat rasterizer
  1663.        // test for transparency
  1664.        if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1665.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1666.           {
  1667.           // alpha version
  1668.           // redo with transparency
  1669.           Draw_Triangle_2DZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  1670.           } // end if
  1671.        else
  1672.           {
  1673.           // non alpha version
  1674.           Draw_Triangle_2DZB_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1675.           }  // end if
  1676.        } // end if
  1677.     else
  1678.     if (rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  1679.        {
  1680.         // {andre take advantage of the data structures later..}
  1681.         // set the vertices
  1682.         face.tvlist[0].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].x;
  1683.         face.tvlist[0].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].y;
  1684.         face.tvlist[0].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[0].z;
  1685.         face.lit_color[0] = rc->rend_list->poly_ptrs[poly]->lit_color[0];
  1686.         face.tvlist[1].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].x;
  1687.         face.tvlist[1].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].y;
  1688.         face.tvlist[1].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[1].z;
  1689.         face.lit_color[1] = rc->rend_list->poly_ptrs[poly]->lit_color[1];
  1690.         face.tvlist[2].x  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].x;
  1691.         face.tvlist[2].y  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].y;
  1692.         face.tvlist[2].z  = (float)rc->rend_list->poly_ptrs[poly]->tvlist[2].z;
  1693.         face.lit_color[2] = rc->rend_list->poly_ptrs[poly]->lit_color[2];
  1694.     // draw the gouraud shaded triangle
  1695.         // test for transparency
  1696.         if ((rc->attr & RENDER_ATTR_ALPHA) &&
  1697.               ((rc->rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_TRANSPARENT) || rc->alpha_override>=0) )
  1698.            {
  1699.            // alpha version
  1700.            // redo with transparency
  1701.            Draw_Gouraud_TriangleZB_Alpha16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch,alpha);
  1702.            } // end if
  1703.         else
  1704.            { 
  1705.            // non alpha
  1706.            Draw_Gouraud_TriangleWTZB2_16(&face, rc->video_buffer, rc->lpitch,rc->zbuffer,rc->zpitch);
  1707.            } // end if
  1708.        } // end if gouraud
  1709.     } // end for poly
  1710. } // end if RENDER_ATTR_ZBUFFER
  1711. } // end Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_3
  1712. ////////////////////////////////////////////////////////////////////////////////////////
  1713. void Draw_Textured_TriangleWTZB3_16(POLYF4DV2_PTR face,  // ptr to face
  1714.                               UCHAR *_dest_buffer,       // pointer to video buffer
  1715.                               int mem_pitch,             // bytes per line, 320, 640 etc.
  1716.                               UCHAR *_zbuffer,           // pointer to z-buffer
  1717.                               int zpitch)                // bytes per line of zbuffer
  1718. {
  1719. // this function draws a textured triangle in 16-bit mode
  1720. int v0=0,
  1721.     v1=1,
  1722. v2=2,
  1723. temp=0,
  1724. tri_type = TRI_TYPE_NONE,
  1725. irestart = INTERP_LHS;
  1726. int dx,dy,dyl,dyr,      // general deltas
  1727.     u,v,z,
  1728.     du,dv,dz,
  1729.     xi,yi,              // the current interpolated x,y
  1730. ui,vi,zi,           // the current interpolated u,v,z
  1731. index_x,index_y,    // looping vars
  1732. x,y,                // hold general x,y
  1733. xstart,
  1734. xend,
  1735. ystart,
  1736. yrestart,
  1737. yend,
  1738. xl,                 
  1739. dxdyl,              
  1740. xr,
  1741. dxdyr,             
  1742. dudyl,    
  1743. ul,
  1744. dvdyl,   
  1745. vl,
  1746. dzdyl,   
  1747. zl,
  1748. dudyr,
  1749. ur,
  1750. dvdyr,
  1751. vr,
  1752. dzdyr,
  1753. zr;
  1754. int x0,y0,tu0,tv0,tz0,    // cached vertices
  1755. x1,y1,tu1,tv1,tz1,
  1756. x2,y2,tu2,tv2,tz2;
  1757. USHORT *screen_ptr  = NULL,
  1758.    *screen_line = NULL,
  1759.    *textmap     = NULL,
  1760.        *dest_buffer = (USHORT *)_dest_buffer,
  1761.        textel;
  1762. UINT  *z_ptr = NULL,
  1763.       *zbuffer = (UINT *)_zbuffer;
  1764. #ifdef DEBUG_ON
  1765. // track rendering stats
  1766.     debug_polys_rendered_per_frame++;
  1767. #endif
  1768. // extract texture map
  1769. textmap = (USHORT *)face->texture->buffer;
  1770. // extract base 2 of texture width
  1771. int texture_shift2 = logbase2ofx[face->texture->width];
  1772. // adjust memory pitch to words, divide by 2
  1773. mem_pitch >>=1;
  1774. // adjust zbuffer pitch for 32 bit alignment
  1775. zpitch >>= 2;
  1776. // apply fill convention to coordinates
  1777. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  1778. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  1779. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  1780. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  1781. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  1782. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  1783. // first trivial clipping rejection tests 
  1784. if (((face->tvlist[0].y < min_clip_y)  && 
  1785.  (face->tvlist[1].y < min_clip_y)  &&
  1786.  (face->tvlist[2].y < min_clip_y)) ||
  1787. ((face->tvlist[0].y > max_clip_y)  && 
  1788.  (face->tvlist[1].y > max_clip_y)  &&
  1789.  (face->tvlist[2].y > max_clip_y)) ||
  1790. ((face->tvlist[0].x < min_clip_x)  && 
  1791.  (face->tvlist[1].x < min_clip_x)  &&
  1792.  (face->tvlist[2].x < min_clip_x)) ||
  1793. ((face->tvlist[0].x > max_clip_x)  && 
  1794.  (face->tvlist[1].x > max_clip_x)  &&
  1795.  (face->tvlist[2].x > max_clip_x)))
  1796.    return;
  1797. // sort vertices
  1798. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  1799. {SWAP(v0,v1,temp);} 
  1800. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  1801. {SWAP(v0,v2,temp);}
  1802. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  1803. {SWAP(v1,v2,temp);}
  1804. // now test for trivial flat sided cases
  1805. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  1806. // set triangle type
  1807. tri_type = TRI_TYPE_FLAT_TOP;
  1808. // sort vertices left to right
  1809. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  1810. {SWAP(v0,v1,temp);}
  1811. } // end if
  1812. else
  1813. // now test for trivial flat sided cases
  1814. if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
  1815. // set triangle type
  1816. tri_type = TRI_TYPE_FLAT_BOTTOM;
  1817. // sort vertices left to right
  1818. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  1819. {SWAP(v1,v2,temp);}
  1820. } // end if
  1821. else
  1822. {
  1823. // must be a general triangle
  1824. tri_type = TRI_TYPE_GENERAL;
  1825. } // end else
  1826. // extract vertices for processing, now that we have order
  1827. x0  = (int)(face->tvlist[v0].x+0.0);
  1828. y0  = (int)(face->tvlist[v0].y+0.0);
  1829. tu0 = (int)(face->tvlist[v0].u0);
  1830. tv0 = (int)(face->tvlist[v0].v0);
  1831. tz0 = (int)(face->tvlist[v0].z+0.5);
  1832. x1  = (int)(face->tvlist[v1].x+0.0);
  1833. y1  = (int)(face->tvlist[v1].y+0.0);
  1834. tu1 = (int)(face->tvlist[v1].u0);
  1835. tv1 = (int)(face->tvlist[v1].v0);
  1836. tz1 = (int)(face->tvlist[v1].z+0.5);
  1837. x2  = (int)(face->tvlist[v2].x+0.0);
  1838. y2  = (int)(face->tvlist[v2].y+0.0);
  1839. tu2 = (int)(face->tvlist[v2].u0);
  1840. tv2 = (int)(face->tvlist[v2].v0);
  1841. tz2 = (int)(face->tvlist[v2].z+0.5);
  1842. // degenerate triangle
  1843. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  1844.    return;
  1845. // set interpolation restart value
  1846. yrestart = y1;
  1847. // what kind of triangle
  1848. if (tri_type & TRI_TYPE_FLAT_MASK)
  1849. {
  1850. if (tri_type == TRI_TYPE_FLAT_TOP)
  1851. {
  1852. // compute all deltas
  1853. dy = (y2 - y0);
  1854. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1855. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1856. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  1857. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  1858. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  1859. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  1860. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  1861. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;  
  1862. // test for y clipping
  1863. if (y0 < min_clip_y)
  1864. {
  1865. // compute overclip
  1866. dy = (min_clip_y - y0);
  1867. // computer new LHS starting values
  1868. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1869. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1870. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1871. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1872. // compute new RHS starting values
  1873. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  1874. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  1875. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  1876. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  1877. // compute new starting y
  1878. ystart = min_clip_y;
  1879. } // end if
  1880. else
  1881. {
  1882. // no clipping
  1883. // set starting values
  1884. xl = (x0 << FIXP16_SHIFT);
  1885. xr = (x1 << FIXP16_SHIFT);
  1886. ul = (tu0 << FIXP16_SHIFT);
  1887. vl = (tv0 << FIXP16_SHIFT);
  1888. zl = (tz0 << FIXP16_SHIFT);
  1889. ur = (tu1 << FIXP16_SHIFT);
  1890. vr = (tv1 << FIXP16_SHIFT);
  1891. zr = (tz1 << FIXP16_SHIFT);
  1892. // set starting y
  1893. ystart = y0;
  1894. } // end else
  1895. } // end if flat top
  1896. else
  1897. {
  1898. // must be flat bottom
  1899. // compute all deltas
  1900. dy = (y1 - y0);
  1901. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  1902. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  1903. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  1904. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy;   
  1905. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1906. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1907. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  1908. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  1909. // test for y clipping
  1910. if (y0 < min_clip_y)
  1911. {
  1912. // compute overclip
  1913. dy = (min_clip_y - y0);
  1914. // computer new LHS starting values
  1915. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1916. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1917. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1918. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  1919. // compute new RHS starting values
  1920. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1921. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1922. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1923. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  1924. // compute new starting y
  1925. ystart = min_clip_y;
  1926. } // end if
  1927. else
  1928. {
  1929. // no clipping
  1930. // set starting values
  1931. xl = (x0 << FIXP16_SHIFT);
  1932. xr = (x0 << FIXP16_SHIFT);
  1933. ul = (tu0 << FIXP16_SHIFT);
  1934. vl = (tv0 << FIXP16_SHIFT);
  1935. zl = (tz0 << FIXP16_SHIFT);
  1936. ur = (tu0 << FIXP16_SHIFT);
  1937. vr = (tv0 << FIXP16_SHIFT);
  1938. zr = (tz0 << FIXP16_SHIFT);
  1939. // set starting y
  1940. ystart = y0;
  1941. } // end else
  1942. } // end else flat bottom
  1943. // test for bottom clip, always
  1944. if ((yend = y2) > max_clip_y)
  1945. yend = max_clip_y;
  1946.     // test for horizontal clipping
  1947. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1948. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1949. (x2 < min_clip_x) || (x2 > max_clip_x))
  1950. {
  1951.     // clip version
  1952. // point screen ptr to starting line
  1953. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1954.     // point zbuffer to starting line
  1955.     z_ptr = zbuffer + (ystart * zpitch);
  1956. for (yi = ystart; yi < yend; yi++)
  1957. {
  1958. // compute span endpoints
  1959. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1960. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1961. // compute starting points for u,v interpolants
  1962. ui = ul + FIXP16_ROUND_UP;
  1963. vi = vl + FIXP16_ROUND_UP;
  1964. zi = zl + FIXP16_ROUND_UP;
  1965. // compute u,v interpolants
  1966. if ((dx = (xend - xstart))>0)
  1967. {
  1968. du = (ur - ul)/dx;
  1969. dv = (vr - vl)/dx;
  1970. dz = (zr - zl)/dx;
  1971. } // end if
  1972. else
  1973. {
  1974. du = (ur - ul);
  1975. dv = (vr - vl);
  1976. dz = (zr - zl);
  1977. } // end else
  1978. ///////////////////////////////////////////////////////////////////////
  1979. // test for x clipping, LHS
  1980. if (xstart < min_clip_x)
  1981. {
  1982. // compute x overlap
  1983. dx = min_clip_x - xstart;
  1984. // slide interpolants over
  1985. ui+=dx*du;
  1986. vi+=dx*dv;
  1987. zi+=dx*dz;
  1988. // reset vars
  1989. xstart = min_clip_x;
  1990. } // end if
  1991. // test for x clipping RHS
  1992. if (xend > max_clip_x)
  1993. xend = max_clip_x;
  1994. ///////////////////////////////////////////////////////////////////////
  1995. // draw span
  1996. for (xi=xstart; xi < xend; xi++)
  1997. {
  1998.             // write thru the z buffer always
  1999.     // write textel
  2000.             // test for transparent pixel
  2001.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2002.    
  2003.             if (textel)
  2004.                {
  2005.                // update z-buffer
  2006.                z_ptr[xi] = zi;           
  2007.                // write pixel
  2008.                screen_ptr[xi] = textel;
  2009.                } // end if
  2010.  
  2011. // interpolate u,v,z
  2012. ui+=du;
  2013. vi+=dv;
  2014. zi+=dz;
  2015. } // end for xi
  2016. // interpolate u,v,x along right and left edge
  2017. xl+=dxdyl;
  2018. ul+=dudyl;
  2019. vl+=dvdyl;
  2020. zl+=dzdyl;
  2021. xr+=dxdyr;
  2022. ur+=dudyr;
  2023. vr+=dvdyr;
  2024. zr+=dzdyr;
  2025.  
  2026. // advance screen ptr
  2027. screen_ptr+=mem_pitch;
  2028.         // advance zbuffer ptr
  2029.         z_ptr+=zpitch;
  2030. } // end for y
  2031. } // end if clip
  2032. else
  2033. {
  2034. // non-clip version
  2035. // point screen ptr to starting line
  2036. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2037.     // point zbuffer to starting line
  2038.     z_ptr = zbuffer + (ystart * zpitch);
  2039. for (yi = ystart; yi < yend; yi++)
  2040. {
  2041. // compute span endpoints
  2042. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2043. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2044. // compute starting points for u,v interpolants
  2045. ui = ul + FIXP16_ROUND_UP;
  2046. vi = vl + FIXP16_ROUND_UP;
  2047. zi = zl + FIXP16_ROUND_UP;
  2048. // compute u,v interpolants
  2049. if ((dx = (xend - xstart))>0)
  2050. {
  2051. du = (ur - ul)/dx;
  2052. dv = (vr - vl)/dx;
  2053. dz = (zr - zl)/dx;
  2054. } // end if
  2055. else
  2056. {
  2057. du = (ur - ul);
  2058. dv = (vr - vl);
  2059. dz = (zr - zl);
  2060. } // end else
  2061. // draw span
  2062. for (xi=xstart; xi < xend; xi++)
  2063. {
  2064.             // write thru the z buffer always
  2065.     // write textel
  2066.             // test for transparent pixel
  2067.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2068.    
  2069.             if (textel)
  2070.                {
  2071.                // update z-buffer
  2072.                z_ptr[xi] = zi;           
  2073.                // write pixel
  2074.                screen_ptr[xi] = textel;
  2075.                } // end if
  2076. // interpolate u,v,z
  2077. ui+=du;
  2078. vi+=dv;
  2079. zi+=dz;
  2080. } // end for xi
  2081. // interpolate u,v,x along right and left edge
  2082. xl+=dxdyl;
  2083. ul+=dudyl;
  2084. vl+=dvdyl;
  2085. zl+=dzdyl;
  2086. xr+=dxdyr;
  2087. ur+=dudyr;
  2088. vr+=dvdyr;
  2089. zr+=dzdyr;
  2090. // advance screen ptr
  2091. screen_ptr+=mem_pitch;
  2092.         // advance zbuffer ptr
  2093.         z_ptr+=zpitch;
  2094. } // end for y
  2095. } // end if non-clipped
  2096. } // end if
  2097. else
  2098. if (tri_type==TRI_TYPE_GENERAL)
  2099. {
  2100. // first test for bottom clip, always
  2101. if ((yend = y2) > max_clip_y)
  2102. yend = max_clip_y;
  2103. // pre-test y clipping status
  2104. if (y1 < min_clip_y)
  2105. {
  2106. // compute all deltas
  2107. // LHS
  2108. dyl = (y2 - y1);
  2109. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  2110. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2111. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  2112. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  2113. // RHS
  2114. dyr = (y2 - y0);
  2115. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2116. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2117. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2118. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  2119. // compute overclip
  2120. dyr = (min_clip_y - y0);
  2121. dyl = (min_clip_y - y1);
  2122. // computer new LHS starting values
  2123. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  2124. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  2125. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  2126. zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  2127. // compute new RHS starting values
  2128. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  2129. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  2130. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  2131. zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  2132. // compute new starting y
  2133. ystart = min_clip_y;
  2134. // test if we need swap to keep rendering left to right
  2135. if (dxdyr > dxdyl)
  2136. {
  2137. SWAP(dxdyl,dxdyr,temp);
  2138. SWAP(dudyl,dudyr,temp);
  2139. SWAP(dvdyl,dvdyr,temp);
  2140. SWAP(dzdyl,dzdyr,temp);
  2141. SWAP(xl,xr,temp);
  2142. SWAP(ul,ur,temp);
  2143. SWAP(vl,vr,temp);
  2144. SWAP(zl,zr,temp);
  2145. SWAP(x1,x2,temp);
  2146. SWAP(y1,y2,temp);
  2147. SWAP(tu1,tu2,temp);
  2148. SWAP(tv1,tv2,temp);
  2149. SWAP(tz1,tz2,temp);
  2150. // set interpolation restart
  2151. irestart = INTERP_RHS;
  2152. } // end if
  2153. } // end if
  2154. else
  2155. if (y0 < min_clip_y)
  2156. {
  2157. // compute all deltas
  2158. // LHS
  2159. dyl = (y1 - y0);
  2160. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2161. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2162. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2163. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;  
  2164. // RHS
  2165. dyr = (y2 - y0);
  2166. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2167. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2168. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2169. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  2170. // compute overclip
  2171. dy = (min_clip_y - y0);
  2172. // computer new LHS starting values
  2173. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2174. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2175. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2176. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2177. // compute new RHS starting values
  2178. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2179. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2180. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2181. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  2182. // compute new starting y
  2183. ystart = min_clip_y;
  2184. // test if we need swap to keep rendering left to right
  2185. if (dxdyr < dxdyl)
  2186. {
  2187. SWAP(dxdyl,dxdyr,temp);
  2188. SWAP(dudyl,dudyr,temp);
  2189. SWAP(dvdyl,dvdyr,temp);
  2190. SWAP(dzdyl,dzdyr,temp);
  2191. SWAP(xl,xr,temp);
  2192. SWAP(ul,ur,temp);
  2193. SWAP(vl,vr,temp);
  2194. SWAP(zl,zr,temp);
  2195. SWAP(x1,x2,temp);
  2196. SWAP(y1,y2,temp);
  2197. SWAP(tu1,tu2,temp);
  2198. SWAP(tv1,tv2,temp);
  2199. SWAP(tz1,tz2,temp);
  2200. // set interpolation restart
  2201. irestart = INTERP_RHS;
  2202. } // end if
  2203. } // end if
  2204. else
  2205. {
  2206. // no initial y clipping
  2207. // compute all deltas
  2208. // LHS
  2209. dyl = (y1 - y0);
  2210. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2211. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2212. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2213. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;   
  2214. // RHS
  2215. dyr = (y2 - y0);
  2216. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  2217. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2218. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2219. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;  
  2220. // no clipping y
  2221. // set starting values
  2222. xl = (x0 << FIXP16_SHIFT);
  2223. xr = (x0 << FIXP16_SHIFT);
  2224. ul = (tu0 << FIXP16_SHIFT);
  2225. vl = (tv0 << FIXP16_SHIFT);
  2226. zl = (tz0 << FIXP16_SHIFT);
  2227. ur = (tu0 << FIXP16_SHIFT);
  2228. vr = (tv0 << FIXP16_SHIFT);
  2229. zr = (tz0 << FIXP16_SHIFT);
  2230. // set starting y
  2231. ystart = y0;
  2232. // test if we need swap to keep rendering left to right
  2233. if (dxdyr < dxdyl)
  2234. {
  2235. SWAP(dxdyl,dxdyr,temp);
  2236. SWAP(dudyl,dudyr,temp);
  2237. SWAP(dvdyl,dvdyr,temp);
  2238. SWAP(dzdyl,dzdyr,temp);
  2239. SWAP(xl,xr,temp);
  2240. SWAP(ul,ur,temp);
  2241. SWAP(vl,vr,temp);
  2242. SWAP(zl,zr,temp);
  2243. SWAP(x1,x2,temp);
  2244. SWAP(y1,y2,temp);
  2245. SWAP(tu1,tu2,temp);
  2246. SWAP(tv1,tv2,temp);
  2247. SWAP(tz1,tz2,temp);
  2248. // set interpolation restart
  2249. irestart = INTERP_RHS;
  2250. } // end if
  2251. } // end else
  2252.     // test for horizontal clipping
  2253. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2254. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2255. (x2 < min_clip_x) || (x2 > max_clip_x))
  2256. {
  2257.     // clip version
  2258. // x clipping
  2259. // point screen ptr to starting line
  2260. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2261.     // point zbuffer to starting line
  2262.     z_ptr = zbuffer + (ystart * zpitch);
  2263. for (yi = ystart; yi < yend; yi++)
  2264. {
  2265. // compute span endpoints
  2266. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2267. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2268. // compute starting points for u,v interpolants
  2269. ui = ul + FIXP16_ROUND_UP;
  2270. vi = vl + FIXP16_ROUND_UP;
  2271. zi = zl + FIXP16_ROUND_UP;
  2272. // compute u,v interpolants
  2273. if ((dx = (xend - xstart))>0)
  2274. {
  2275. du = (ur - ul)/dx;
  2276. dv = (vr - vl)/dx;
  2277. dz = (zr - zl)/dx;
  2278. } // end if
  2279. else
  2280. {
  2281. du = (ur - ul);
  2282. dv = (vr - vl);
  2283. dz = (zr - zl);
  2284. } // end else
  2285. ///////////////////////////////////////////////////////////////////////
  2286. // test for x clipping, LHS
  2287. if (xstart < min_clip_x)
  2288. {
  2289. // compute x overlap
  2290. dx = min_clip_x - xstart;
  2291. // slide interpolants over
  2292. ui+=dx*du;
  2293. vi+=dx*dv;
  2294. zi+=dx*dz;
  2295. // set x to left clip edge
  2296. xstart = min_clip_x;
  2297. } // end if
  2298. // test for x clipping RHS
  2299. if (xend > max_clip_x)
  2300. xend = max_clip_x;
  2301. ///////////////////////////////////////////////////////////////////////
  2302. // draw span
  2303. for (xi=xstart; xi < xend; xi++)
  2304. {
  2305.             // write thru the z buffer always
  2306.     // write textel
  2307.             // test for transparent pixel
  2308.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2309.    
  2310.             if (textel)
  2311.                {
  2312.                // update z-buffer
  2313.                z_ptr[xi] = zi;           
  2314.                // write pixel
  2315.                screen_ptr[xi] = textel;
  2316.                } // end if
  2317. // interpolate u,v,z
  2318. ui+=du;
  2319. vi+=dv;
  2320. zi+=dz;
  2321. } // end for xi
  2322. // interpolate u,v,x along right and left edge
  2323. xl+=dxdyl;
  2324. ul+=dudyl;
  2325. vl+=dvdyl;
  2326. zl+=dzdyl;
  2327. xr+=dxdyr;
  2328. ur+=dudyr;
  2329. vr+=dvdyr;
  2330. zr+=dzdyr;
  2331. // advance screen ptr
  2332. screen_ptr+=mem_pitch;
  2333.         // advance zbuffer ptr
  2334.         z_ptr+=zpitch;
  2335. // test for yi hitting second region, if so change interpolant
  2336. if (yi==yrestart)
  2337. {
  2338.     // test interpolation side change flag
  2339. if (irestart == INTERP_LHS)
  2340. {
  2341. // LHS
  2342. dyl = (y2 - y1);
  2343. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2344. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2345. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2346. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  2347. // set starting values
  2348. xl = (x1  << FIXP16_SHIFT);
  2349. ul = (tu1 << FIXP16_SHIFT);
  2350. vl = (tv1 << FIXP16_SHIFT);
  2351. zl = (tz1 << FIXP16_SHIFT);
  2352. // interpolate down on LHS to even up
  2353. xl+=dxdyl;
  2354. ul+=dudyl;
  2355. vl+=dvdyl;
  2356. zl+=dzdyl;
  2357. } // end if
  2358. else
  2359. {
  2360. // RHS
  2361. dyr = (y1 - y2);
  2362. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2363. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2364. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2365. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;  
  2366. // set starting values
  2367. xr = (x2  << FIXP16_SHIFT);
  2368. ur = (tu2 << FIXP16_SHIFT);
  2369. vr = (tv2 << FIXP16_SHIFT);
  2370. zr = (tz2 << FIXP16_SHIFT);
  2371. // interpolate down on RHS to even up
  2372. xr+=dxdyr;
  2373. ur+=dudyr;
  2374. vr+=dvdyr;
  2375. zr+=dzdyr;
  2376. } // end else
  2377. } // end if
  2378. } // end for y
  2379. } // end if
  2380. else
  2381. {
  2382. // no x clipping
  2383. // point screen ptr to starting line
  2384. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2385.     // point zbuffer to starting line
  2386.     z_ptr = zbuffer + (ystart * zpitch);
  2387. for (yi = ystart; yi < yend; yi++)
  2388. {
  2389. // compute span endpoints
  2390. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2391. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2392. // compute starting points for u,v interpolants
  2393. ui = ul + FIXP16_ROUND_UP;
  2394. vi = vl + FIXP16_ROUND_UP;
  2395. zi = zl + FIXP16_ROUND_UP;
  2396. // compute u,v interpolants
  2397. if ((dx = (xend - xstart))>0)
  2398. {
  2399. du = (ur - ul)/dx;
  2400. dv = (vr - vl)/dx;
  2401. dz = (zr - zl)/dx;
  2402. } // end if
  2403. else
  2404. {
  2405. du = (ur - ul);
  2406. dv = (vr - vl);
  2407. dz = (zr - zl);
  2408. } // end else
  2409. // draw span
  2410. for (xi=xstart; xi < xend; xi++)
  2411. {
  2412.             // write thru the z buffer always
  2413.     // write textel
  2414.             // test for transparent pixel
  2415.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2416.    
  2417.             if (textel)
  2418.                {
  2419.                // update z-buffer
  2420.                z_ptr[xi] = zi;           
  2421.                // write pixel
  2422.                screen_ptr[xi] = textel;
  2423.                } // end if
  2424. // interpolate u,v
  2425. ui+=du;
  2426. vi+=dv;
  2427. zi+=dz;
  2428. } // end for xi
  2429. // interpolate u,v,x along right and left edge
  2430. xl+=dxdyl;
  2431. ul+=dudyl;
  2432. vl+=dvdyl;
  2433. zl+=dzdyl;
  2434. xr+=dxdyr;
  2435. ur+=dudyr;
  2436. vr+=dvdyr;
  2437. zr+=dzdyr;
  2438. // advance screen ptr
  2439. screen_ptr+=mem_pitch;
  2440.         // advance zbuffer ptr
  2441.         z_ptr+=zpitch;
  2442. // test for yi hitting second region, if so change interpolant
  2443. if (yi==yrestart)
  2444. {
  2445. // test interpolation side change flag
  2446. if (irestart == INTERP_LHS)
  2447. {
  2448. // LHS
  2449. dyl = (y2 - y1);
  2450. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2451. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2452. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2453. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;   
  2454. // set starting values
  2455. xl = (x1  << FIXP16_SHIFT);
  2456. ul = (tu1 << FIXP16_SHIFT);
  2457. vl = (tv1 << FIXP16_SHIFT);
  2458. zl = (tz1 << FIXP16_SHIFT);
  2459. // interpolate down on LHS to even up
  2460. xl+=dxdyl;
  2461. ul+=dudyl;
  2462. vl+=dvdyl;
  2463. zl+=dzdyl;
  2464. } // end if
  2465. else
  2466. {
  2467. // RHS
  2468. dyr = (y1 - y2);
  2469. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2470. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2471. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2472. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr; 
  2473. // set starting values
  2474. xr = (x2  << FIXP16_SHIFT);
  2475. ur = (tu2 << FIXP16_SHIFT);
  2476. vr = (tv2 << FIXP16_SHIFT);
  2477. zr = (tz2 << FIXP16_SHIFT);
  2478. // interpolate down on RHS to even up
  2479. xr+=dxdyr;
  2480. ur+=dudyr;
  2481. vr+=dvdyr;
  2482. zr+=dzdyr;
  2483. } // end else
  2484. } // end if
  2485. } // end for y
  2486.    } // end else
  2487. } // end if
  2488. } // end Draw_Textured_TriangleWTZB3_16
  2489. ///////////////////////////////////////////////////////////////////////////////
  2490. void Draw_Textured_TriangleFSWTZB3_16(POLYF4DV2_PTR face, // ptr to face
  2491.                                  UCHAR *_dest_buffer,  // pointer to video buffer
  2492.                                  int mem_pitch,        // bytes per line, 320, 640 etc.
  2493.                                  UCHAR *_zbuffer,       // pointer to z-buffer
  2494.                                  int zpitch)          // bytes per line of zbuffer
  2495. {
  2496. // this function draws a textured triangle in 16-bit mode with flat shading
  2497. int v0=0,
  2498.     v1=1,
  2499. v2=2,
  2500. temp=0,
  2501. tri_type = TRI_TYPE_NONE,
  2502. irestart = INTERP_LHS;
  2503. int dx,dy,dyl,dyr,      // general deltas
  2504.     u,v,z,
  2505.     du,dv,dz,
  2506.     xi,yi,              // the current interpolated x,y
  2507. ui,vi,zi,            // the current interpolated u,v,z
  2508. index_x,index_y,    // looping vars
  2509. x,y,                // hold general x,y
  2510. xstart,
  2511. xend,
  2512. ystart,
  2513. yrestart,
  2514. yend,
  2515. xl,                 
  2516. dxdyl,              
  2517. xr,
  2518. dxdyr,             
  2519. dudyl,    
  2520. ul,
  2521. dzdyl,    
  2522. zl,
  2523. dvdyl,   
  2524. vl,
  2525. dudyr,
  2526. ur,
  2527. dvdyr,
  2528. vr,
  2529. dzdyr,
  2530. zr;
  2531. USHORT r_base, g_base, b_base,
  2532.        r_textel, g_textel, b_textel, textel;
  2533. int x0,y0,tu0,tv0,tz0,    // cached vertices
  2534. x1,y1,tu1,tv1,tz1,
  2535. x2,y2,tu2,tv2,tz2;
  2536. USHORT *screen_ptr  = NULL,
  2537.    *screen_line = NULL,
  2538.    *textmap     = NULL,
  2539.        *dest_buffer = (USHORT *)_dest_buffer;
  2540. UINT  *z_ptr = NULL,
  2541.       *zbuffer = (UINT *)_zbuffer;
  2542. #ifdef DEBUG_ON
  2543. // track rendering stats
  2544.     debug_polys_rendered_per_frame++;
  2545. #endif
  2546. // extract texture map
  2547. textmap = (USHORT *)face->texture->buffer;
  2548. // extract base 2 of texture width
  2549. int texture_shift2 = logbase2ofx[face->texture->width];
  2550. // adjust memory pitch to words, divide by 2
  2551. mem_pitch >>=1;
  2552. // adjust zbuffer pitch for 32 bit alignment
  2553. zpitch >>= 2;
  2554. // apply fill convention to coordinates
  2555. face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
  2556. face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
  2557. face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
  2558. face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
  2559. face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
  2560. face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
  2561. // first trivial clipping rejection tests 
  2562. if (((face->tvlist[0].y < min_clip_y)  && 
  2563.  (face->tvlist[1].y < min_clip_y)  &&
  2564.  (face->tvlist[2].y < min_clip_y)) ||
  2565. ((face->tvlist[0].y > max_clip_y)  && 
  2566.  (face->tvlist[1].y > max_clip_y)  &&
  2567.  (face->tvlist[2].y > max_clip_y)) ||
  2568. ((face->tvlist[0].x < min_clip_x)  && 
  2569.  (face->tvlist[1].x < min_clip_x)  &&
  2570.  (face->tvlist[2].x < min_clip_x)) ||
  2571. ((face->tvlist[0].x > max_clip_x)  && 
  2572.  (face->tvlist[1].x > max_clip_x)  &&
  2573.  (face->tvlist[2].x > max_clip_x)))
  2574.    return;
  2575. // sort vertices
  2576. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  2577. {SWAP(v0,v1,temp);} 
  2578. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  2579. {SWAP(v0,v2,temp);}
  2580. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  2581. {SWAP(v1,v2,temp);}
  2582. // now test for trivial flat sided cases
  2583. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  2584. // set triangle type
  2585. tri_type = TRI_TYPE_FLAT_TOP;
  2586. // sort vertices left to right
  2587. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  2588. {SWAP(v0,v1,temp);}
  2589. } // end if
  2590. else
  2591. // now test for trivial flat sided cases
  2592. if (FCMP( face->tvlist[v1].y, face->tvlist[v2].y) )
  2593. // set triangle type
  2594. tri_type = TRI_TYPE_FLAT_BOTTOM;
  2595. // sort vertices left to right
  2596. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  2597. {SWAP(v1,v2,temp);}
  2598. } // end if
  2599. else
  2600. {
  2601. // must be a general triangle
  2602. tri_type = TRI_TYPE_GENERAL;
  2603. } // end else
  2604. // extract base color of lit poly, so we can modulate texture a bit
  2605. // for lighting
  2606. _RGB565FROM16BIT(face->lit_color[0], &r_base, &g_base, &b_base);
  2607. // extract vertices for processing, now that we have order
  2608. x0  = (int)(face->tvlist[v0].x+0.0);
  2609. y0  = (int)(face->tvlist[v0].y+0.0);
  2610. tu0 = (int)(face->tvlist[v0].u0);
  2611. tv0 = (int)(face->tvlist[v0].v0);
  2612. tz0 = (int)(face->tvlist[v0].z+0.5);
  2613. x1  = (int)(face->tvlist[v1].x+0.0);
  2614. y1  = (int)(face->tvlist[v1].y+0.0);
  2615. tu1 = (int)(face->tvlist[v1].u0);
  2616. tv1 = (int)(face->tvlist[v1].v0);
  2617. tz1 = (int)(face->tvlist[v1].z+0.5);
  2618. x2  = (int)(face->tvlist[v2].x+0.0);
  2619. y2  = (int)(face->tvlist[v2].y+0.0);
  2620. tu2 = (int)(face->tvlist[v2].u0);
  2621. tv2 = (int)(face->tvlist[v2].v0);
  2622. tz2 = (int)(face->tvlist[v2].z+0.5);
  2623. // degenerate triangle
  2624. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  2625.    return;
  2626. // set interpolation restart value
  2627. yrestart = y1;
  2628. // what kind of triangle
  2629. if (tri_type & TRI_TYPE_FLAT_MASK)
  2630. {
  2631. if (tri_type == TRI_TYPE_FLAT_TOP)
  2632. {
  2633. // compute all deltas
  2634. dy = (y2 - y0);
  2635. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2636. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2637. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  2638. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy;    
  2639. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  2640. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  2641. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  2642. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;   
  2643. // test for y clipping
  2644. if (y0 < min_clip_y)
  2645. {
  2646. // compute overclip
  2647. dy = (min_clip_y - y0);
  2648. // computer new LHS starting values
  2649. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2650. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2651. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2652. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2653. // compute new RHS starting values
  2654. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  2655. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  2656. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  2657. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  2658. // compute new starting y
  2659. ystart = min_clip_y;
  2660. } // end if
  2661. else
  2662. {
  2663. // no clipping
  2664. // set starting values
  2665. xl = (x0 << FIXP16_SHIFT);
  2666. xr = (x1 << FIXP16_SHIFT);
  2667. ul = (tu0 << FIXP16_SHIFT);
  2668. vl = (tv0 << FIXP16_SHIFT);
  2669. zl = (tz0 << FIXP16_SHIFT);
  2670. ur = (tu1 << FIXP16_SHIFT);
  2671. vr = (tv1 << FIXP16_SHIFT);
  2672. zr = (tz1 << FIXP16_SHIFT);
  2673. // set starting y
  2674. ystart = y0;
  2675. } // end else
  2676. } // end if flat top
  2677. else
  2678. {
  2679. // must be flat bottom
  2680. // compute all deltas
  2681. dy = (y1 - y0);
  2682. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  2683. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  2684. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  2685. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy; 
  2686. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2687. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2688. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  2689. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  2690. // test for y clipping
  2691. if (y0 < min_clip_y)
  2692. {
  2693. // compute overclip
  2694. dy = (min_clip_y - y0);
  2695. // computer new LHS starting values
  2696. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2697. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2698. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2699. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2700. // compute new RHS starting values
  2701. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2702. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2703. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2704. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  2705. // compute new starting y
  2706. ystart = min_clip_y;
  2707. } // end if
  2708. else
  2709. {
  2710. // no clipping
  2711. // set starting values
  2712. xl = (x0 << FIXP16_SHIFT);
  2713. xr = (x0 << FIXP16_SHIFT);
  2714. ul = (tu0 << FIXP16_SHIFT);
  2715. vl = (tv0 << FIXP16_SHIFT);
  2716. zl = (tz0 << FIXP16_SHIFT);
  2717. ur = (tu0 << FIXP16_SHIFT);
  2718. vr = (tv0 << FIXP16_SHIFT);
  2719. zr = (tz0 << FIXP16_SHIFT);
  2720. // set starting y
  2721. ystart = y0;
  2722. } // end else
  2723. } // end else flat bottom
  2724. // test for bottom clip, always
  2725. if ((yend = y2) > max_clip_y)
  2726. yend = max_clip_y;
  2727.     // test for horizontal clipping
  2728. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2729. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2730. (x2 < min_clip_x) || (x2 > max_clip_x))
  2731. {
  2732.     // clip version
  2733. // point screen ptr to starting line
  2734. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2735.     // point zbuffer to starting line
  2736.     z_ptr = zbuffer + (ystart * zpitch);
  2737. for (yi = ystart; yi < yend; yi++)
  2738. {
  2739. // compute span endpoints
  2740. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2741. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2742. // compute starting points for u,v interpolants
  2743. ui = ul + FIXP16_ROUND_UP;
  2744. vi = vl + FIXP16_ROUND_UP;
  2745. zi = zl + FIXP16_ROUND_UP;
  2746. // compute u,v interpolants
  2747. if ((dx = (xend - xstart))>0)
  2748. {
  2749. du = (ur - ul)/dx;
  2750. dv = (vr - vl)/dx;
  2751. dz = (zr - zl)/dx;
  2752. } // end if
  2753. else
  2754. {
  2755. du = (ur - ul);
  2756. dv = (vr - vl);
  2757. dz = (zr - zl);
  2758. } // end else
  2759. ///////////////////////////////////////////////////////////////////////
  2760. // test for x clipping, LHS
  2761. if (xstart < min_clip_x)
  2762. {
  2763. // compute x overlap
  2764. dx = min_clip_x - xstart;
  2765. // slide interpolants over
  2766. ui+=dx*du;
  2767. vi+=dx*dv;
  2768. zi+=dx*dz;
  2769. // reset vars
  2770. xstart = min_clip_x;
  2771. } // end if
  2772. // test for x clipping RHS
  2773. if (xend > max_clip_x)
  2774. xend = max_clip_x;
  2775. ///////////////////////////////////////////////////////////////////////
  2776. // draw span
  2777. for (xi=xstart; xi < xend; xi++)
  2778. {
  2779.             // write thru the z buffer always
  2780. // write textel
  2781.             // test for transparent pixel
  2782.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2783.    
  2784.             if (textel)
  2785.                {
  2786.                // extract rgb components
  2787.                r_textel  = ((textel >> 11)       ); 
  2788.                g_textel  = ((textel >> 5)  & 0x3f); 
  2789.                b_textel =   (textel        & 0x1f);
  2790.                // modulate textel with lit background color
  2791.                r_textel*=r_base; 
  2792.                g_textel*=g_base;
  2793.                b_textel*=b_base;
  2794.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  2795.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  2796.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  2797.                // and they all cancel out for the most part, but we will need logical anding, we will do
  2798.                // it later when we optimize more...
  2799.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  2800.                // update z-buffer
  2801.                z_ptr[xi] = zi;                     
  2802.                } // end if
  2803. // interpolate u,v,z
  2804. ui+=du;
  2805. vi+=dv;
  2806. zi+=dz;
  2807. } // end for xi
  2808. // interpolate u,v,x along right and left edge
  2809. xl+=dxdyl;
  2810. ul+=dudyl;
  2811. vl+=dvdyl;
  2812. zl+=dzdyl;
  2813. xr+=dxdyr;
  2814. ur+=dudyr;
  2815. vr+=dvdyr;
  2816. zr+=dzdyr;
  2817.  
  2818. // advance screen ptr
  2819. screen_ptr+=mem_pitch;
  2820.         // advance zbuffer ptr
  2821.         z_ptr+=zpitch;
  2822. } // end for y
  2823. } // end if clip
  2824. else
  2825. {
  2826. // non-clip version
  2827. // point screen ptr to starting line
  2828. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2829.     // point zbuffer to starting line
  2830.     z_ptr = zbuffer + (ystart * zpitch);
  2831. for (yi = ystart; yi < yend; yi++)
  2832. {
  2833. // compute span endpoints
  2834. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2835. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2836. // compute starting points for u,v interpolants
  2837. ui = ul + FIXP16_ROUND_UP;
  2838. vi = vl + FIXP16_ROUND_UP;
  2839. zi = zl + FIXP16_ROUND_UP;
  2840. // compute u,v interpolants
  2841. if ((dx = (xend - xstart))>0)
  2842. {
  2843. du = (ur - ul)/dx;
  2844. dv = (vr - vl)/dx;
  2845. dz = (zr - zl)/dx;
  2846. } // end if
  2847. else
  2848. {
  2849. du = (ur - ul);
  2850. dv = (vr - vl);
  2851.             dz = (zr - zl);
  2852. } // end else
  2853. // draw span
  2854. for (xi=xstart; xi < xend; xi++)
  2855. {
  2856.             // write thru the z buffer always
  2857.    // write textel
  2858.             // test for transparent pixel
  2859.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2860.    
  2861.             if (textel)
  2862.                {
  2863.                // extract rgb components
  2864.                r_textel  = ((textel >> 11)       ); 
  2865.                g_textel  = ((textel >> 5)  & 0x3f); 
  2866.                b_textel =   (textel        & 0x1f);
  2867.                // modulate textel with lit background color
  2868.                r_textel*=r_base; 
  2869.                g_textel*=g_base;
  2870.                b_textel*=b_base;
  2871.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  2872.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  2873.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  2874.                // and they all cancel out for the most part, but we will need logical anding, we will do
  2875.                // it later when we optimize more...
  2876.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  2877.                // update z-buffer
  2878.                z_ptr[xi] = zi;                     
  2879.               } // end if
  2880. // interpolate u,v,z
  2881. ui+=du;
  2882. vi+=dv;
  2883.             zi+=dz;
  2884. } // end for xi
  2885. // interpolate u,v,x along right and left edge
  2886. xl+=dxdyl;
  2887. ul+=dudyl;
  2888. vl+=dvdyl;
  2889.     zl+=dzdyl;
  2890. xr+=dxdyr;
  2891. ur+=dudyr;
  2892. vr+=dvdyr;
  2893.         zr+=dzdyr;
  2894. // advance screen ptr
  2895. screen_ptr+=mem_pitch;
  2896.         // advance zbuffer ptr
  2897.         z_ptr+=zpitch;
  2898. } // end for y
  2899. } // end if non-clipped
  2900. } // end if
  2901. else
  2902. if (tri_type==TRI_TYPE_GENERAL)
  2903. {
  2904. // first test for bottom clip, always
  2905. if ((yend = y2) > max_clip_y)
  2906. yend = max_clip_y;
  2907. // pre-test y clipping status
  2908. if (y1 < min_clip_y)
  2909. {
  2910. // compute all deltas
  2911. // LHS
  2912. dyl = (y2 - y1);
  2913. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  2914. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2915. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  2916.         dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;    
  2917. // RHS
  2918. dyr = (y2 - y0);
  2919. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2920. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2921. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2922.         dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  2923. // compute overclip
  2924. dyr = (min_clip_y - y0);
  2925. dyl = (min_clip_y - y1);
  2926. // computer new LHS starting values
  2927. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  2928. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  2929. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  2930.         zl = dzdyl*dyl + (tz1 << FIXP16_SHIFT);
  2931. // compute new RHS starting values
  2932. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  2933. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  2934. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  2935.         zr = dzdyr*dyr + (tz0 << FIXP16_SHIFT);
  2936. // compute new starting y
  2937. ystart = min_clip_y;
  2938. // test if we need swap to keep rendering left to right
  2939. if (dxdyr > dxdyl)
  2940. {
  2941. SWAP(dxdyl,dxdyr,temp);
  2942. SWAP(dudyl,dudyr,temp);
  2943. SWAP(dvdyl,dvdyr,temp);
  2944. SWAP(dzdyl,dzdyr,temp);
  2945. SWAP(xl,xr,temp);
  2946. SWAP(ul,ur,temp);
  2947. SWAP(vl,vr,temp);
  2948. SWAP(zl,zr,temp);
  2949. SWAP(x1,x2,temp);
  2950. SWAP(y1,y2,temp);
  2951. SWAP(tu1,tu2,temp);
  2952. SWAP(tv1,tv2,temp);
  2953. SWAP(tz1,tz2,temp);
  2954. // set interpolation restart
  2955. irestart = INTERP_RHS;
  2956. } // end if
  2957. } // end if
  2958. else
  2959. if (y0 < min_clip_y)
  2960. {
  2961. // compute all deltas
  2962. // LHS
  2963. dyl = (y1 - y0);
  2964. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2965. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2966. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2967.         dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;    
  2968. // RHS
  2969. dyr = (y2 - y0);
  2970. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2971. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2972. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2973.         dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  2974. // compute overclip
  2975. dy = (min_clip_y - y0);
  2976. // computer new LHS starting values
  2977. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2978. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2979. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2980.         zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  2981. // compute new RHS starting values
  2982. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2983. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2984. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2985.         zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  2986. // compute new starting y
  2987. ystart = min_clip_y;
  2988. // test if we need swap to keep rendering left to right
  2989. if (dxdyr < dxdyl)
  2990. {
  2991. SWAP(dxdyl,dxdyr,temp);
  2992. SWAP(dudyl,dudyr,temp);
  2993. SWAP(dvdyl,dvdyr,temp);
  2994. SWAP(dzdyl,dzdyr,temp);
  2995. SWAP(xl,xr,temp);
  2996. SWAP(ul,ur,temp);
  2997. SWAP(vl,vr,temp);
  2998. SWAP(zl,zr,temp);
  2999. SWAP(x1,x2,temp);
  3000. SWAP(y1,y2,temp);
  3001. SWAP(tu1,tu2,temp);
  3002. SWAP(tv1,tv2,temp);
  3003. SWAP(tz1,tz2,temp);
  3004. // set interpolation restart
  3005. irestart = INTERP_RHS;
  3006. } // end if
  3007. } // end if
  3008. else
  3009. {
  3010. // no initial y clipping
  3011. // compute all deltas
  3012. // LHS
  3013. dyl = (y1 - y0);
  3014. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  3015. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  3016. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  3017.         dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dyl;    
  3018. // RHS
  3019. dyr = (y2 - y0);
  3020. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  3021. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  3022. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  3023.         dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dyr;   
  3024. // no clipping y
  3025. // set starting values
  3026. xl = (x0 << FIXP16_SHIFT);
  3027. xr = (x0 << FIXP16_SHIFT);
  3028. ul = (tu0 << FIXP16_SHIFT);
  3029. vl = (tv0 << FIXP16_SHIFT);
  3030.         zl = (tz0 << FIXP16_SHIFT);
  3031. ur = (tu0 << FIXP16_SHIFT);
  3032. vr = (tv0 << FIXP16_SHIFT);
  3033.         zr = (tz0 << FIXP16_SHIFT);
  3034. // set starting y
  3035. ystart = y0;
  3036. // test if we need swap to keep rendering left to right
  3037. if (dxdyr < dxdyl)
  3038. {
  3039. SWAP(dxdyl,dxdyr,temp);
  3040. SWAP(dudyl,dudyr,temp);
  3041. SWAP(dvdyl,dvdyr,temp);
  3042. SWAP(dzdyl,dzdyr,temp);
  3043. SWAP(xl,xr,temp);
  3044. SWAP(ul,ur,temp);
  3045. SWAP(vl,vr,temp);
  3046. SWAP(zl,zr,temp);
  3047. SWAP(x1,x2,temp);
  3048. SWAP(y1,y2,temp);
  3049. SWAP(tu1,tu2,temp);
  3050. SWAP(tv1,tv2,temp);
  3051. SWAP(tz1,tz2,temp);
  3052. // set interpolation restart
  3053. irestart = INTERP_RHS;
  3054. } // end if
  3055. } // end else
  3056.     // test for horizontal clipping
  3057. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  3058. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  3059. (x2 < min_clip_x) || (x2 > max_clip_x))
  3060. {
  3061.     // clip version
  3062. // x clipping
  3063. // point screen ptr to starting line
  3064. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3065.     // point zbuffer to starting line
  3066.     z_ptr = zbuffer + (ystart * zpitch);
  3067. for (yi = ystart; yi < yend; yi++)
  3068. {
  3069. // compute span endpoints
  3070. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3071. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3072. // compute starting points for u,v interpolants
  3073. ui = ul + FIXP16_ROUND_UP;
  3074. vi = vl + FIXP16_ROUND_UP;
  3075.         zi = zl + FIXP16_ROUND_UP;
  3076. // compute u,v interpolants
  3077. if ((dx = (xend - xstart))>0)
  3078. {
  3079. du = (ur - ul)/dx;
  3080. dv = (vr - vl)/dx;
  3081.             dz = (zr - zl)/dx;
  3082. } // end if
  3083. else
  3084. {
  3085. du = (ur - ul);
  3086. dv = (vr - vl);
  3087.             dz = (zr - zl);
  3088. } // end else
  3089. ///////////////////////////////////////////////////////////////////////
  3090. // test for x clipping, LHS
  3091. if (xstart < min_clip_x)
  3092. {
  3093. // compute x overlap
  3094. dx = min_clip_x - xstart;
  3095. // slide interpolants over
  3096. ui+=dx*du;
  3097. vi+=dx*dv;
  3098. zi+=dx*dz;
  3099. // set x to left clip edge
  3100. xstart = min_clip_x;
  3101. } // end if
  3102. // test for x clipping RHS
  3103. if (xend > max_clip_x)
  3104. xend = max_clip_x;
  3105. ///////////////////////////////////////////////////////////////////////
  3106. // draw span
  3107. for (xi=xstart; xi < xend; xi++)
  3108. {
  3109.             // write thru the z buffer always
  3110.    // write textel
  3111.             // test for transparent pixel
  3112.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  3113.    
  3114.             if (textel)
  3115.                {
  3116.                // extract rgb components
  3117.                r_textel  = ((textel >> 11)       ); 
  3118.                g_textel  = ((textel >> 5)  & 0x3f); 
  3119.                b_textel =   (textel        & 0x1f);
  3120.                // modulate textel with lit background color
  3121.                r_textel*=r_base; 
  3122.                g_textel*=g_base;
  3123.                b_textel*=b_base;
  3124.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  3125.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  3126.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  3127.                // and they all cancel out for the most part, but we will need logical anding, we will do
  3128.                // it later when we optimize more...
  3129.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  3130.                // update z-buffer
  3131.                z_ptr[xi] = zi;   
  3132.                } // end if                  
  3133. // interpolate u,v
  3134. ui+=du;
  3135. vi+=dv;
  3136.             zi+=dz;
  3137. } // end for xi
  3138. // interpolate u,v,x along right and left edge
  3139. xl+=dxdyl;
  3140. ul+=dudyl;
  3141. vl+=dvdyl;
  3142. zl+=dzdyl;
  3143. xr+=dxdyr;
  3144. ur+=dudyr;
  3145. vr+=dvdyr;
  3146. zr+=dzdyr;
  3147. // advance screen ptr
  3148. screen_ptr+=mem_pitch;
  3149.         // advance zbuffer ptr
  3150.         z_ptr+=zpitch;
  3151. // test for yi hitting second region, if so change interpolant
  3152. if (yi==yrestart)
  3153. {
  3154.       // test interpolation side change flag
  3155. if (irestart == INTERP_LHS)
  3156. {
  3157. // LHS
  3158. dyl = (y2 - y1);
  3159. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  3160. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  3161. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  3162. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl;  
  3163. // set starting values
  3164. xl = (x1  << FIXP16_SHIFT);
  3165. ul = (tu1 << FIXP16_SHIFT);
  3166. vl = (tv1 << FIXP16_SHIFT);
  3167. zl = (tz1 << FIXP16_SHIFT);
  3168. // interpolate down on LHS to even up
  3169. xl+=dxdyl;
  3170. ul+=dudyl;
  3171. vl+=dvdyl;
  3172. zl+=dzdyl;
  3173. } // end if
  3174. else
  3175. {
  3176. // RHS
  3177. dyr = (y1 - y2);
  3178. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  3179. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  3180. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  3181. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  3182. // set starting values
  3183. xr = (x2  << FIXP16_SHIFT);
  3184. ur = (tu2 << FIXP16_SHIFT);
  3185. vr = (tv2 << FIXP16_SHIFT);
  3186. zr = (tz2 << FIXP16_SHIFT);
  3187. // interpolate down on RHS to even up
  3188. xr+=dxdyr;
  3189. ur+=dudyr;
  3190. vr+=dvdyr;
  3191. zr+=dzdyr;
  3192. } // end else
  3193. } // end if
  3194. } // end for y
  3195. } // end if
  3196. else
  3197. {
  3198. // no x clipping
  3199. // point screen ptr to starting line
  3200. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3201.     // point zbuffer to starting line
  3202.     z_ptr = zbuffer + (ystart * zpitch);
  3203. for (yi = ystart; yi < yend; yi++)
  3204. {
  3205. // compute span endpoints
  3206. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3207. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3208. // compute starting points for u,v,z interpolants
  3209. ui = ul + FIXP16_ROUND_UP;
  3210. vi = vl + FIXP16_ROUND_UP;
  3211. zi = zl + FIXP16_ROUND_UP;
  3212. // compute u,v interpolants
  3213. if ((dx = (xend - xstart))>0)
  3214. {
  3215. du = (ur - ul)/dx;
  3216. dv = (vr - vl)/dx;
  3217.             dz = (zr - zl)/dx;
  3218. } // end if
  3219. else
  3220. {
  3221. du = (ur - ul);
  3222. dv = (vr - vl);
  3223.             dz = (zr - zl);
  3224. } // end else
  3225. // draw span
  3226. for (xi=xstart; xi < xend; xi++)
  3227. {
  3228.             // write thru the z buffer always
  3229.    // write textel
  3230.             // test for transparent pixel
  3231.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  3232.    
  3233.             if (textel)
  3234.                {
  3235.                // extract rgb components
  3236.                r_textel  = ((textel >> 11)       ); 
  3237.                g_textel  = ((textel >> 5)  & 0x3f); 
  3238.                b_textel =   (textel        & 0x1f);
  3239.                // modulate textel with lit background color
  3240.                r_textel*=r_base; 
  3241.                g_textel*=g_base;
  3242.                b_textel*=b_base;
  3243.                // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  3244.                // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  3245.                // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  3246.                // and they all cancel out for the most part, but we will need logical anding, we will do
  3247.                // it later when we optimize more...
  3248.                screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  3249.                // update z-buffer
  3250.                z_ptr[xi] = zi;   
  3251.                } // end if    
  3252. // interpolate u,v,z
  3253. ui+=du;
  3254. vi+=dv;
  3255.             zi+=dz;
  3256. } // end for xi
  3257. // interpolate u,v,x along right and left edge
  3258. xl+=dxdyl;
  3259. ul+=dudyl;
  3260. vl+=dvdyl;
  3261.         zl+=dzdyl;
  3262. xr+=dxdyr;
  3263. ur+=dudyr;
  3264. vr+=dvdyr;
  3265.         zr+=dzdyr;
  3266. // advance screen ptr
  3267. screen_ptr+=mem_pitch;
  3268.         // advance zbuffer ptr
  3269.         z_ptr+=zpitch;
  3270. // test for yi hitting second region, if so change interpolant
  3271. if (yi==yrestart)
  3272. {
  3273. // test interpolation side change flag
  3274. if (irestart == INTERP_LHS)
  3275. {
  3276. // LHS
  3277. dyl = (y2 - y1);
  3278. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  3279. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  3280. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  3281. dzdyl = ((tz2 - tz1) << FIXP16_SHIFT)/dyl; 
  3282. // set starting values
  3283. xl = (x1  << FIXP16_SHIFT);
  3284. ul = (tu1 << FIXP16_SHIFT);
  3285. vl = (tv1 << FIXP16_SHIFT);
  3286. zl = (tz1 << FIXP16_SHIFT);
  3287. // interpolate down on LHS to even up
  3288. xl+=dxdyl;
  3289. ul+=dudyl;
  3290. vl+=dvdyl;
  3291. zl+=dzdyl;
  3292. } // end if
  3293. else
  3294. {
  3295. // RHS
  3296. dyr = (y1 - y2);
  3297. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  3298. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  3299. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  3300. dzdyr = ((tz1 - tz2) << FIXP16_SHIFT)/dyr;   
  3301. // set starting values
  3302. xr = (x2  << FIXP16_SHIFT);
  3303. ur = (tu2 << FIXP16_SHIFT);
  3304. vr = (tv2 << FIXP16_SHIFT);
  3305. zr = (tz2 << FIXP16_SHIFT);
  3306. // interpolate down on RHS to even up
  3307. xr+=dxdyr;
  3308. ur+=dudyr;
  3309. vr+=dvdyr;
  3310. zr+=dzdyr;
  3311. } // end else
  3312. } // end if
  3313. } // end for y
  3314.    } // end else
  3315. } // end if
  3316. } // end Draw_Textured_TriangleFSWTZB3_16
  3317. //////////////////////////////////////////////////////////////////////////////
  3318. void Draw_Textured_TriangleGSWTZB2_16(POLYF4DV2_PTR face,   // ptr to face
  3319.                                  UCHAR *_dest_buffer, // pointer to video buffer
  3320.                                  int mem_pitch,       // bytes per line, 320, 640 etc.
  3321.                                  UCHAR *_zbuffer,       // pointer to z-buffer
  3322.                                  int zpitch)          // bytes per line of zbuffer
  3323. {
  3324. // this function draws a textured gouraud shaded polygon, and z bufferedbased on the affine texture mapper, 
  3325. // we simply interpolate the (R,G,B) values across the polygons along with the texture coordinates
  3326. // and then modulate to get the final color 
  3327. int v0=0,
  3328.     v1=1,
  3329. v2=2,
  3330. temp=0,
  3331. tri_type = TRI_TYPE_NONE,
  3332. irestart = INTERP_LHS;
  3333. int dx,dy,dyl,dyr,      // general deltas
  3334.     u,v,w,z, s,t,
  3335.     du,dv,dw,dz, ds, dt, 
  3336.     xi,yi,             // the current interpolated x,y
  3337. ui,vi,wi,zi, si, ti,    // the current interpolated u,v
  3338. index_x,index_y,    // looping vars
  3339. x,y,                // hold general x,y
  3340. xstart,
  3341. xend,
  3342. ystart,
  3343. yrestart,
  3344. yend,
  3345. xl,                 
  3346. dxdyl,              
  3347. xr,
  3348. dxdyr,             
  3349. dudyl,    
  3350. ul,
  3351. dvdyl,   
  3352. vl,
  3353. dwdyl,   
  3354. wl,
  3355. dzdyl,   
  3356. zl,
  3357. dsdyl,    
  3358. sl,
  3359. dtdyl,   
  3360. tl,
  3361. dudyr,
  3362. ur,
  3363. dvdyr,
  3364. vr,
  3365. dwdyr,
  3366. wr,
  3367. dzdyr,
  3368. zr,
  3369. dsdyr,
  3370. sr,
  3371. dtdyr,
  3372. tr;
  3373. int x0,y0,tu0,tv0,tw0, tz0, ts0,tt0,    // cached vertices
  3374. x1,y1,tu1,tv1,tw1, tz1, ts1,tt1,
  3375. x2,y2,tu2,tv2,tw2, tz2, ts2,tt2;
  3376. int r_base0, g_base0, b_base0,
  3377.     r_base1, g_base1, b_base1,
  3378.     r_base2, g_base2, b_base2;
  3379. UINT r_textel, g_textel, b_textel;
  3380. USHORT textel;
  3381. USHORT *screen_ptr  = NULL,
  3382.    *screen_line = NULL,
  3383.    *textmap     = NULL,
  3384.        *dest_buffer = (USHORT *)_dest_buffer;
  3385. UINT  *z_ptr = NULL,
  3386.       *zbuffer = (UINT *)_zbuffer;
  3387. #ifdef DEBUG_ON
  3388. // track rendering stats
  3389.     debug_polys_rendered_per_frame++;
  3390. #endif
  3391. // extract texture map
  3392. textmap = (USHORT *)face->texture->buffer;
  3393. // extract base 2 of texture width
  3394. int texture_shift2 = logbase2ofx[face->texture->width];
  3395. // adjust memory pitch to words, divide by 2
  3396. mem_pitch >>=1;
  3397. // adjust zbuffer pitch for 32 bit alignment
  3398. zpitch >>= 2;
  3399. // apply fill convention to coordinates
  3400. face->tvlist[0].x = (int)(face->tvlist[0].x+0.0);
  3401. face->tvlist[0].y = (int)(face->tvlist[0].y+0.0);
  3402. face->tvlist[1].x = (int)(face->tvlist[1].x+0.0);
  3403. face->tvlist[1].y = (int)(face->tvlist[1].y+0.0);
  3404. face->tvlist[2].x = (int)(face->tvlist[2].x+0.0);
  3405. face->tvlist[2].y = (int)(face->tvlist[2].y+0.0);
  3406. // first trivial clipping rejection tests 
  3407. if (((face->tvlist[0].y < min_clip_y)  && 
  3408.  (face->tvlist[1].y < min_clip_y)  &&
  3409.  (face->tvlist[2].y < min_clip_y)) ||
  3410. ((face->tvlist[0].y > max_clip_y)  && 
  3411.  (face->tvlist[1].y > max_clip_y)  &&
  3412.  (face->tvlist[2].y > max_clip_y)) ||
  3413. ((face->tvlist[0].x < min_clip_x)  && 
  3414.  (face->tvlist[1].x < min_clip_x)  &&
  3415.  (face->tvlist[2].x < min_clip_x)) ||
  3416. ((face->tvlist[0].x > max_clip_x)  && 
  3417.  (face->tvlist[1].x > max_clip_x)  &&
  3418.  (face->tvlist[2].x > max_clip_x)))
  3419.    return;
  3420. // sort vertices
  3421. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  3422. {SWAP(v0,v1,temp);} 
  3423. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  3424. {SWAP(v0,v2,temp);}
  3425. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  3426. {SWAP(v1,v2,temp);}
  3427. // now test for trivial flat sided cases
  3428. if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
  3429. // set triangle type
  3430. tri_type = TRI_TYPE_FLAT_TOP;
  3431. // sort vertices left to right
  3432. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  3433. {SWAP(v0,v1,temp);}
  3434. } // end if
  3435. else
  3436. // now test for trivial flat sided cases
  3437. if (FCMP(face->tvlist[v1].y, face->tvlist[v2].y) )
  3438. // set triangle type
  3439. tri_type = TRI_TYPE_FLAT_BOTTOM;
  3440. // sort vertices left to right
  3441. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  3442. {SWAP(v1,v2,temp);}
  3443. } // end if
  3444. else
  3445. {
  3446. // must be a general triangle
  3447. tri_type = TRI_TYPE_GENERAL;
  3448. } // end else
  3449. // assume 5.6.5 format -- sorry!
  3450. // we can't afford a function call in the inner loops, so we must write 
  3451. // two hard coded versions, if we want support for both 5.6.5, and 5.5.5
  3452. _RGB565FROM16BIT(face->lit_color[v0], &r_base0, &g_base0, &b_base0);
  3453. _RGB565FROM16BIT(face->lit_color[v1], &r_base1, &g_base1, &b_base1);
  3454. _RGB565FROM16BIT(face->lit_color[v2], &r_base2, &g_base2, &b_base2);
  3455. // scale to 8 bit 
  3456. r_base0 <<= 3;
  3457. g_base0 <<= 2;
  3458. b_base0 <<= 3;
  3459. // scale to 8 bit 
  3460. r_base1 <<= 3;
  3461. g_base1 <<= 2;
  3462. b_base1 <<= 3;
  3463. // scale to 8 bit 
  3464. r_base2 <<= 3;
  3465. g_base2 <<= 2;
  3466. b_base2 <<= 3;
  3467. // extract vertices for processing, now that we have order
  3468. x0  = (int)(face->tvlist[v0].x+0.0);
  3469. y0  = (int)(face->tvlist[v0].y+0.0);
  3470. tz0 = (int)(face->tvlist[v0].z+0.5);
  3471. ts0 = (int)(face->tvlist[v0].u0);
  3472. tt0 = (int)(face->tvlist[v0].v0);
  3473. tu0 = r_base0;
  3474. tv0 = g_base0; 
  3475. tw0 = b_base0; 
  3476. x1  = (int)(face->tvlist[v1].x+0.0);
  3477. y1  = (int)(face->tvlist[v1].y+0.0);
  3478. tz1 = (int)(face->tvlist[v1].z+0.5);
  3479. ts1 = (int)(face->tvlist[v1].u0);
  3480. tt1 = (int)(face->tvlist[v1].v0);
  3481. tu1 = r_base1;
  3482. tv1 = g_base1; 
  3483. tw1 = b_base1; 
  3484. x2  = (int)(face->tvlist[v2].x+0.0);
  3485. y2  = (int)(face->tvlist[v2].y+0.0);
  3486. tz2 = (int)(face->tvlist[v2].z+0.5);
  3487. ts2 = (int)(face->tvlist[v2].u0);
  3488. tt2 = (int)(face->tvlist[v2].v0);
  3489. tu2 = r_base2; 
  3490. tv2 = g_base2; 
  3491. tw2 = b_base2; 
  3492. // degenerate triangle
  3493. if ( ((x0 == x1) && (x1 == x2)) || ((y0 ==  y1) && (y1 == y2)))
  3494.    return;
  3495. // set interpolation restart value
  3496. yrestart = y1;
  3497. // what kind of triangle
  3498. if (tri_type & TRI_TYPE_FLAT_MASK)
  3499. {
  3500. if (tri_type == TRI_TYPE_FLAT_TOP)
  3501. {
  3502. // compute all deltas
  3503. dy = (y2 - y0);
  3504. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  3505. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  3506. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  3507. dwdyl = ((tw2 - tw0) << FIXP16_SHIFT)/dy;  
  3508. dzdyl = ((tz2 - tz0) << FIXP16_SHIFT)/dy; 
  3509.     dsdyl = ((ts2 - ts0) << FIXP16_SHIFT)/dy;    
  3510. dtdyl = ((tt2 - tt0) << FIXP16_SHIFT)/dy;  
  3511. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  3512. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  3513. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  3514. dwdyr = ((tw2 - tw1) << FIXP16_SHIFT)/dy;   
  3515. dzdyr = ((tz2 - tz1) << FIXP16_SHIFT)/dy;   
  3516. dsdyr = ((ts2 - ts1) << FIXP16_SHIFT)/dy;   
  3517. dtdyr = ((tt2 - tt1) << FIXP16_SHIFT)/dy;   
  3518. // test for y clipping
  3519. if (y0 < min_clip_y)
  3520. {
  3521. // compute overclip
  3522. dy = (min_clip_y - y0);
  3523. // computer new LHS starting values
  3524. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  3525. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  3526. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  3527. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  3528. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  3529. sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
  3530. tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
  3531. // compute new RHS starting values
  3532. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  3533. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  3534. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  3535. wr = dwdyr*dy + (tw1 << FIXP16_SHIFT);
  3536. zr = dzdyr*dy + (tz1 << FIXP16_SHIFT);
  3537. sr = dsdyr*dy + (ts1 << FIXP16_SHIFT);
  3538. tr = dtdyr*dy + (tt1 << FIXP16_SHIFT);
  3539. // compute new starting y
  3540. ystart = min_clip_y;
  3541. } // end if
  3542. else
  3543. {
  3544. // no clipping
  3545. // set starting values
  3546. xl = (x0 << FIXP16_SHIFT);
  3547. xr = (x1 << FIXP16_SHIFT);
  3548. ul = (tu0 << FIXP16_SHIFT);
  3549. vl = (tv0 << FIXP16_SHIFT);
  3550. wl = (tw0 << FIXP16_SHIFT);
  3551. zl = (tz0 << FIXP16_SHIFT);
  3552. sl = (ts0 << FIXP16_SHIFT);
  3553. tl = (tt0 << FIXP16_SHIFT);
  3554. ur = (tu1 << FIXP16_SHIFT);
  3555. vr = (tv1 << FIXP16_SHIFT);
  3556. wr = (tw1 << FIXP16_SHIFT);
  3557. zr = (tz1 << FIXP16_SHIFT);
  3558. sr = (ts1 << FIXP16_SHIFT);
  3559. tr = (tt1 << FIXP16_SHIFT);
  3560. // set starting y
  3561. ystart = y0;
  3562. } // end else
  3563. } // end if flat top
  3564. else
  3565. {
  3566. // must be flat bottom
  3567. // compute all deltas
  3568. dy = (y1 - y0);
  3569. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  3570. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  3571. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  3572. dwdyl = ((tw1 - tw0) << FIXP16_SHIFT)/dy; 
  3573. dzdyl = ((tz1 - tz0) << FIXP16_SHIFT)/dy; 
  3574. dsdyl = ((ts1 - ts0) << FIXP16_SHIFT)/dy;    
  3575. dtdyl = ((tt1 - tt0) << FIXP16_SHIFT)/dy; 
  3576. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  3577. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  3578. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  3579. dwdyr = ((tw2 - tw0) << FIXP16_SHIFT)/dy;   
  3580. dzdyr = ((tz2 - tz0) << FIXP16_SHIFT)/dy;   
  3581. dsdyr = ((ts2 - ts0) << FIXP16_SHIFT)/dy;   
  3582. dtdyr = ((tt2 - tt0) << FIXP16_SHIFT)/dy;   
  3583. // test for y clipping
  3584. if (y0 < min_clip_y)
  3585. {
  3586. // compute overclip
  3587. dy = (min_clip_y - y0);
  3588. // computer new LHS starting values
  3589. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  3590. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  3591. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  3592. wl = dwdyl*dy + (tw0 << FIXP16_SHIFT);
  3593. zl = dzdyl*dy + (tz0 << FIXP16_SHIFT);
  3594. sl = dsdyl*dy + (ts0 << FIXP16_SHIFT);
  3595. tl = dtdyl*dy + (tt0 << FIXP16_SHIFT);
  3596. // compute new RHS starting values
  3597. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  3598. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  3599. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  3600. wr = dwdyr*dy + (tw0 << FIXP16_SHIFT);
  3601. zr = dzdyr*dy + (tz0 << FIXP16_SHIFT);
  3602. sr = dsdyr*dy + (ts0 << FIXP16_SHIFT);
  3603. tr = dtdyr*dy + (tt0 << FIXP16_SHIFT);
  3604. // compute new starting y
  3605. ystart = min_clip_y;
  3606. } // end if
  3607. else
  3608. {
  3609. // no clipping
  3610. // set starting values
  3611. xl = (x0 << FIXP16_SHIFT);
  3612. xr = (x0 << FIXP16_SHIFT);
  3613. ul = (tu0 << FIXP16_SHIFT);
  3614. vl = (tv0 << FIXP16_SHIFT);
  3615. wl = (tw0 << FIXP16_SHIFT);
  3616. zl = (tz0 << FIXP16_SHIFT);
  3617. sl = (ts0 << FIXP16_SHIFT);
  3618. tl = (tt0 << FIXP16_SHIFT);
  3619. ur = (tu0 << FIXP16_SHIFT);
  3620. vr = (tv0 << FIXP16_SHIFT);
  3621. wr = (tw0 << FIXP16_SHIFT);
  3622. zr = (tz0 << FIXP16_SHIFT);
  3623. sr = (ts0 << FIXP16_SHIFT);
  3624. tr = (tt0 << FIXP16_SHIFT);
  3625. // set starting y
  3626. ystart = y0;
  3627. } // end else
  3628. } // end else flat bottom
  3629. // test for bottom clip, always
  3630. if ((yend = y2) > max_clip_y)
  3631. yend = max_clip_y;
  3632.     // test for horizontal clipping
  3633. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  3634. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  3635. (x2 < min_clip_x) || (x2 > max_clip_x))
  3636. {
  3637.     // clip version
  3638. // point screen ptr to starting line
  3639. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3640.     // point zbuffer to starting line
  3641.     z_ptr = zbuffer + (ystart * zpitch);
  3642. for (yi = ystart; yi < yend; yi++)
  3643. {
  3644. // compute span endpoints
  3645. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3646. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3647. // compute starting points for u,v,w interpolants
  3648. ui = ul + FIXP16_ROUND_UP;
  3649. vi = vl + FIXP16_ROUND_UP;
  3650. wi = wl + FIXP16_ROUND_UP;
  3651. zi = zl + FIXP16_ROUND_UP;
  3652.         si = sl + FIXP16_ROUND_UP;
  3653. ti = tl + FIXP16_ROUND_UP;
  3654. // compute u,v interpolants
  3655. if ((dx = (xend - xstart))>0)
  3656. {
  3657. du = (ur - ul)/dx;
  3658. dv = (vr - vl)/dx;
  3659. dw = (wr - wl)/dx;
  3660. dz = (zr - zl)/dx;
  3661. ds = (sr - sl)/dx;
  3662. dt = (tr - tl)/dx;
  3663. } // end if
  3664. else
  3665. {
  3666. du = (ur - ul);
  3667. dv = (vr - vl);
  3668. dw = (wr - wl);
  3669. dz = (zr - zl);
  3670. ds = (sr - sl);
  3671. dt = (tr - tl);
  3672. } // end else
  3673. ///////////////////////////////////////////////////////////////////////
  3674. // test for x clipping, LHS
  3675. if (xstart < min_clip_x)
  3676. {
  3677. // compute x overlap
  3678. dx = min_clip_x - xstart;
  3679. // slide interpolants over
  3680. ui+=dx*du;
  3681. vi+=dx*dv;
  3682. wi+=dx*dw;
  3683. zi+=dx*dz;
  3684. si+=dx*ds;
  3685. ti+=dx*dt;
  3686. // reset vars
  3687. xstart = min_clip_x;
  3688. } // end if
  3689. // test for x clipping RHS
  3690. if (xend > max_clip_x)
  3691. xend = max_clip_x;
  3692. ///////////////////////////////////////////////////////////////////////
  3693. // draw span
  3694. for (xi=xstart; xi < xend; xi++)
  3695. {
  3696. // write textel assume 5.6.5
  3697.             // write thru z buffer always
  3698.     // get textel first
  3699.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  3700.             if (textel)
  3701.             {
  3702.            
  3703.             // extract rgb components
  3704.             r_textel  = ((textel >> 11)       ); 
  3705.             g_textel  = ((textel >> 5)  & 0x3f); 
  3706.             b_textel =   (textel        & 0x1f);
  3707.             // modulate textel with gouraud shading
  3708.             r_textel*=ui; 
  3709.             g_textel*=vi;
  3710.             b_textel*=wi;
  3711.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  3712.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  3713.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  3714.             // and they all cancel out for the most part, but we will need logical anding, we will do
  3715.             // it later when we optimize more...
  3716.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  3717.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  3718.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  3719.             // update z-buffer
  3720.             z_ptr[xi] = zi;   
  3721.             } // end if
  3722. // interpolate u,v
  3723. ui+=du;
  3724. vi+=dv;
  3725. wi+=dw;
  3726. zi+=dz;
  3727. si+=ds;
  3728. ti+=dt;
  3729. } // end for xi
  3730. // interpolate u,v,w,x along right and left edge
  3731. xl+=dxdyl;
  3732. ul+=dudyl;
  3733. vl+=dvdyl;
  3734. wl+=dwdyl;
  3735. zl+=dzdyl;
  3736. sl+=dsdyl;
  3737. tl+=dtdyl;
  3738. xr+=dxdyr;
  3739. ur+=dudyr;
  3740. vr+=dvdyr;
  3741. wr+=dwdyr;
  3742. zr+=dzdyr;
  3743.  
  3744. sr+=dsdyr;
  3745. tr+=dtdyr;
  3746. // advance screen ptr
  3747. screen_ptr+=mem_pitch;
  3748.         // advance zbuffer ptr
  3749.         z_ptr+=zpitch;
  3750. } // end for y
  3751. } // end if clip
  3752. else
  3753. {
  3754. // non-clip version
  3755. // point screen ptr to starting line
  3756. screen_ptr = dest_buffer + (ystart * mem_pitch);
  3757.     // point zbuffer to starting line
  3758.     z_ptr = zbuffer + (ystart * zpitch);
  3759. for (yi = ystart; yi < yend; yi++)
  3760. {
  3761. // compute span endpoints
  3762. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3763. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  3764. // compute starting points for u,v,w interpolants
  3765. ui = ul + FIXP16_ROUND_UP;
  3766. vi = vl + FIXP16_ROUND_UP;
  3767. wi = wl + FIXP16_ROUND_UP;
  3768. zi = zl + FIXP16_ROUND_UP;
  3769. si = sl + FIXP16_ROUND_UP;
  3770. ti = tl + FIXP16_ROUND_UP;
  3771. // compute u,v interpolants
  3772. if ((dx = (xend - xstart))>0)
  3773. {
  3774. du = (ur - ul)/dx;
  3775. dv = (vr - vl)/dx;
  3776. dw = (wr - wl)/dx;
  3777. dz = (zr - zl)/dx;
  3778. ds = (sr - sl)/dx;
  3779. dt = (tr - tl)/dx;
  3780. } // end if
  3781. else
  3782. {
  3783. du = (ur - ul);
  3784. dv = (vr - vl);
  3785. dw = (wr - wl);
  3786. dz = (zr - zl);
  3787. ds = (sr - sl);
  3788. dt = (tr - tl);
  3789. } // end else
  3790. // draw span
  3791. for (xi=xstart; xi < xend; xi++)
  3792. {
  3793. // write textel assume 5.6.5
  3794.             // write thru z buffer always
  3795.     // get textel first
  3796.   textel = textmap[(si >> FIXP16_SHIFT) + ((ti >> FIXP16_SHIFT) << texture_shift2)];
  3797.             if (textel)
  3798.             {
  3799.            
  3800.             // extract rgb components
  3801.             r_textel  = ((textel >> 11)       ); 
  3802.             g_textel  = ((textel >> 5)  & 0x3f); 
  3803.             b_textel =   (textel        & 0x1f);
  3804.             // modulate textel with gouraud shading
  3805.             r_textel*=ui; 
  3806.             g_textel*=vi;
  3807.             b_textel*=wi;
  3808.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  3809.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  3810.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  3811.             // and they all cancel out for the most part, but we will need logical anding, we will do
  3812.             // it later when we optimize more...
  3813.             screen_ptr[xi] = ((b_textel >> (FIXP16_SHIFT+8)) + 
  3814.                              ((g_textel >> (FIXP16_SHIFT+8)) << 5) + 
  3815.                              ((r_textel >> (FIXP16_SHIFT+8)) << 11));
  3816.             // update z-buffer
  3817.             z_ptr[xi] = zi;   
  3818.             } // end if
  3819. // interpolate u,v