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

游戏

开发平台:

Visual C++

  1.     Write_Error("nSurface Desc = 0x%.4x, num_verts = %d, vert_indices [%d, %d, %d]", 
  2.                                                          poly_surface_desc, 
  3.                                                          poly_num_verts, 
  4.                                                          obj->plist[poly].vert[0],
  5.                                                          obj->plist[poly].vert[1],
  6.                                                          obj->plist[poly].vert[2]);
  7.     // now we that we have the vertex list and we have entered the polygon
  8.     // vertex index data into the polygon itself, now let's analyze the surface
  9.     // descriptor and set the fields for the polygon based on the description
  10.     // extract out each field of data from the surface descriptor
  11.     // first let's get the single/double sided stuff out of the way
  12.     if ((poly_surface_desc & PLX_2SIDED_FLAG))
  13.        {
  14.        SET_BIT(obj->plist[poly].attr, POLY4DV2_ATTR_2SIDED);
  15.        Write_Error("n2 sided.");
  16.        } // end if
  17.     else
  18.        {
  19.        // one sided
  20.        Write_Error("n1 sided.");
  21.        } // end else
  22.     // now let's set the color type and color
  23.     if ((poly_surface_desc & PLX_COLOR_MODE_RGB_FLAG)) 
  24.        {
  25.        // this is an RGB 4.4.4 surface
  26.        SET_BIT(obj->plist[poly].attr,POLY4DV2_ATTR_RGB16);
  27.  
  28.        // now extract color and copy into polygon color
  29.        // field in proper 16-bit format 
  30.        // 0x0RGB is the format, 4 bits per pixel 
  31.        int red   = ((poly_surface_desc & 0x0f00) >> 8);
  32.        int green = ((poly_surface_desc & 0x00f0) >> 4);
  33.        int blue  = (poly_surface_desc & 0x000f);
  34.        // although the data is always in 4.4.4 format, the graphics card
  35.        // is either 5.5.5 or 5.6.5, but our virtual color system translates
  36.        // 8.8.8 into 5.5.5 or 5.6.5 for us, but we have to first scale all
  37.        // these 4.4.4 values into 8.8.8
  38.        obj->plist[poly].color = RGB16Bit(red*16, green*16, blue*16);
  39.        Write_Error("nRGB color = [%d, %d, %d]", red, green, blue);
  40.        } // end if
  41.     else
  42.        {
  43.        // this is an 8-bit color indexed surface
  44.        SET_BIT(obj->plist[poly].attr,POLY4DV2_ATTR_8BITCOLOR);
  45.        // and simple extract the last 8 bits and that's the color index
  46.        obj->plist[poly].color = (poly_surface_desc & 0x00ff);
  47.        
  48.        Write_Error("n8-bit color index = %d", obj->plist[poly].color);
  49.        } // end else
  50.    // handle shading mode
  51.    int shade_mode = (poly_surface_desc & PLX_SHADE_MODE_MASK);
  52.    // set polygon shading mode
  53.    switch(shade_mode)
  54.          {
  55.          case PLX_SHADE_MODE_PURE_FLAG: {
  56.          SET_BIT(obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_PURE);
  57.          Write_Error("nShade mode = pure");
  58.          } break;
  59.          case PLX_SHADE_MODE_FLAT_FLAG: {
  60.          SET_BIT(obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_FLAT);
  61.          Write_Error("nShade mode = flat");
  62.          } break;
  63.          case PLX_SHADE_MODE_GOURAUD_FLAG: {
  64.          SET_BIT(obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_GOURAUD);
  65.          
  66.          // the vertices from this polygon all need normals, set that in the flags attribute
  67.          SET_BIT(obj->vlist_local[ obj->plist[poly].vert[0] ].attr, VERTEX4DTV1_ATTR_NORMAL); 
  68.          SET_BIT(obj->vlist_local[ obj->plist[poly].vert[1] ].attr, VERTEX4DTV1_ATTR_NORMAL); 
  69.          SET_BIT(obj->vlist_local[ obj->plist[poly].vert[2] ].attr, VERTEX4DTV1_ATTR_NORMAL); 
  70.          Write_Error("nShade mode = gouraud");
  71.          } break;
  72.          case PLX_SHADE_MODE_PHONG_FLAG: {
  73.          SET_BIT(obj->plist[poly].attr, POLY4DV2_ATTR_SHADE_MODE_PHONG);
  74.          // the vertices from this polygon all need normals, set that in the flags attribute
  75.          SET_BIT(obj->vlist_local[ obj->plist[poly].vert[0] ].attr, VERTEX4DTV1_ATTR_NORMAL); 
  76.          SET_BIT(obj->vlist_local[ obj->plist[poly].vert[1] ].attr, VERTEX4DTV1_ATTR_NORMAL); 
  77.          SET_BIT(obj->vlist_local[ obj->plist[poly].vert[2] ].attr, VERTEX4DTV1_ATTR_NORMAL); 
  78.          Write_Error("nShade mode = phong");
  79.          } break;
  80.          default: break;
  81.          } // end switch
  82.     // set the material mode to ver. 1.0 emulation
  83.     SET_BIT(obj->plist[poly].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
  84.     // finally set the polygon to active
  85.     obj->plist[poly].state = POLY4DV2_STATE_ACTIVE;    
  86.     // point polygon vertex list to object's vertex list
  87.     // note that this is redundant since the polylist is contained
  88.     // within the object in this case and its up to the user to select
  89.     // whether the local or transformed vertex list is used when building up
  90.     // polygon geometry, might be a better idea to set to NULL in the context
  91.     // of polygons that are part of an object
  92.     obj->plist[poly].vlist = obj->vlist_local; 
  93.     // set texture coordinate list, this is needed
  94.     obj->plist[poly].tlist = obj->tlist;
  95.     } // end for poly
  96. // compute the polygon normal lengths
  97. Compute_OBJECT4DV2_Poly_Normals(obj);
  98. // compute vertex normals for any gouraud shaded polys
  99. Compute_OBJECT4DV2_Vertex_Normals(obj);
  100. // close the file
  101. fclose(fp);
  102. // return success
  103. return(1);
  104. } // end Load_OBJECT4DV2_PLG
  105. ////////////////////////////////////////////////////////////////
  106. void Reset_RENDERLIST4DV2(RENDERLIST4DV2_PTR rend_list)
  107. {
  108. // this function intializes and resets the sent render list and
  109. // redies it for polygons/faces to be inserted into it
  110. // note that the render list in this version is composed
  111. // of an array FACE4DV1 pointer objects, you call this
  112. // function each frame
  113. // since we are tracking the number of polys in the
  114. // list via num_polys we can set it to 0
  115. // but later we will want a more robust scheme if
  116. // we generalize the linked list more and disconnect
  117. // it from the polygon pointer list
  118. rend_list->num_polys = 0; // that was hard!
  119. }  // end Reset_RENDERLIST4DV2
  120. ////////////////////////////////////////////////////////////////
  121. void Draw_RENDERLIST4DV2_Wire16(RENDERLIST4DV2_PTR rend_list, 
  122.                                 UCHAR *video_buffer, int lpitch)
  123. {
  124. // this function "executes" the render list or in other words
  125. // draws all the faces in the list in wire frame 16bit mode
  126. // note there is no need to sort wire frame polygons
  127. // at this point, all we have is a list of polygons and it's time
  128. // to draw them
  129. for (int poly=0; poly < rend_list->num_polys; poly++)
  130.     {
  131.     // render this polygon if and only if it's not clipped, not culled,
  132.     // active, and visible, note however the concecpt of "backface" is 
  133.     // irrelevant in a wire frame engine though
  134.     if (!(rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  135.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  136.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  137.        continue; // move onto next poly
  138.     // draw the triangle edge one, note that clipping was already set up
  139.     // by 2D initialization, so line clipper will clip all polys out
  140.     // of the 2D screen/window boundary
  141.     Draw_Clip_Line16(rend_list->poly_ptrs[poly]->tvlist[0].x, 
  142.                      rend_list->poly_ptrs[poly]->tvlist[0].y,
  143.                      rend_list->poly_ptrs[poly]->tvlist[1].x, 
  144.                      rend_list->poly_ptrs[poly]->tvlist[1].y,
  145.                      rend_list->poly_ptrs[poly]->lit_color[0],
  146.                      video_buffer, lpitch);
  147.     Draw_Clip_Line16(rend_list->poly_ptrs[poly]->tvlist[1].x, 
  148.                      rend_list->poly_ptrs[poly]->tvlist[1].y,
  149.                      rend_list->poly_ptrs[poly]->tvlist[2].x, 
  150.                      rend_list->poly_ptrs[poly]->tvlist[2].y,
  151.                      rend_list->poly_ptrs[poly]->lit_color[0],
  152.                      video_buffer, lpitch);
  153.     Draw_Clip_Line16(rend_list->poly_ptrs[poly]->tvlist[2].x, 
  154.                      rend_list->poly_ptrs[poly]->tvlist[2].y,
  155.                      rend_list->poly_ptrs[poly]->tvlist[0].x, 
  156.                      rend_list->poly_ptrs[poly]->tvlist[0].y,
  157.                      rend_list->poly_ptrs[poly]->lit_color[0],
  158.                      video_buffer, lpitch);
  159. // track rendering stats
  160. #ifdef DEBUG_ON
  161. debug_polys_rendered_per_frame++;
  162. #endif
  163.     } // end for poly
  164. } // end Draw_RENDERLIST4DV2_Wire16
  165. /////////////////////////////////////////////////////////////
  166. void Draw_RENDERLIST4DV2_Wire(RENDERLIST4DV2_PTR rend_list, 
  167.                               UCHAR *video_buffer, int lpitch)
  168. {
  169. // this function "executes" the render list or in other words
  170. // draws all the faces in the list in wire frame 8bit mode
  171. // note there is no need to sort wire frame polygons
  172. // at this point, all we have is a list of polygons and it's time
  173. // to draw them
  174. for (int poly=0; poly < rend_list->num_polys; poly++)
  175.     {
  176.     // render this polygon if and only if it's not clipped, not culled,
  177.     // active, and visible, note however the concecpt of "backface" is 
  178.     // irrelevant in a wire frame engine though
  179.     if (!(rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  180.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  181.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  182.        continue; // move onto next poly
  183.     // draw the triangle edge one, note that clipping was already set up
  184.     // by 2D initialization, so line clipper will clip all polys out
  185.     // of the 2D screen/window boundary
  186.     Draw_Clip_Line(rend_list->poly_ptrs[poly]->tvlist[0].x, 
  187.                    rend_list->poly_ptrs[poly]->tvlist[0].y,
  188.                    rend_list->poly_ptrs[poly]->tvlist[1].x, 
  189.                    rend_list->poly_ptrs[poly]->tvlist[1].y,
  190.                    rend_list->poly_ptrs[poly]->lit_color[0],
  191.                    video_buffer, lpitch);
  192.     Draw_Clip_Line(rend_list->poly_ptrs[poly]->tvlist[1].x, 
  193.                    rend_list->poly_ptrs[poly]->tvlist[1].y,
  194.                    rend_list->poly_ptrs[poly]->tvlist[2].x, 
  195.                    rend_list->poly_ptrs[poly]->tvlist[2].y,
  196.                    rend_list->poly_ptrs[poly]->lit_color[0],
  197.                    video_buffer, lpitch);
  198.     Draw_Clip_Line(rend_list->poly_ptrs[poly]->tvlist[2].x, 
  199.                    rend_list->poly_ptrs[poly]->tvlist[2].y,
  200.                    rend_list->poly_ptrs[poly]->tvlist[0].x, 
  201.                    rend_list->poly_ptrs[poly]->tvlist[0].y,
  202.                    rend_list->poly_ptrs[poly]->lit_color[0],
  203.                    video_buffer, lpitch);
  204. // track rendering stats
  205. #ifdef DEBUG_ON
  206. debug_polys_rendered_per_frame++;
  207. #endif
  208.     } // end for poly
  209. } // end Draw_RENDERLIST4DV2_Wire
  210. ///////////////////////////////////////////////////////////////
  211. void Draw_RENDERLIST4DV2_Solid16(RENDERLIST4DV2_PTR rend_list, 
  212.                               UCHAR *video_buffer, 
  213.   int lpitch)
  214. {
  215. // 16-bit version
  216. // this function "executes" the render list or in other words
  217. // draws all the faces in the list, the function will call the 
  218. // proper rasterizer based on the lighting model of the polygons
  219. POLYF4DV2 face; // temp face used to render polygon
  220. // at this point, all we have is a list of polygons and it's time
  221. // to draw them
  222. for (int poly=0; poly < rend_list->num_polys; poly++)
  223.     {
  224.     // render this polygon if and only if it's not clipped, not culled,
  225.     // active, and visible, note however the concecpt of "backface" is 
  226.     // irrelevant in a wire frame engine though
  227.     if (!(rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  228.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  229.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  230.        continue; // move onto next poly
  231.     // need to test for textured first, since a textured poly can either
  232.     // be emissive, or flat shaded, hence we need to call different
  233.     // rasterizers    
  234.     if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  235.        {
  236.        // set the vertices
  237.        face.tvlist[0].x = (int)rend_list->poly_ptrs[poly]->tvlist[0].x;
  238.        face.tvlist[0].y = (int)rend_list->poly_ptrs[poly]->tvlist[0].y;
  239.        face.tvlist[0].u0 = (int)rend_list->poly_ptrs[poly]->tvlist[0].u0;
  240.        face.tvlist[0].v0 = (int)rend_list->poly_ptrs[poly]->tvlist[0].v0;
  241.        face.tvlist[1].x = (int)rend_list->poly_ptrs[poly]->tvlist[1].x;
  242.        face.tvlist[1].y = (int)rend_list->poly_ptrs[poly]->tvlist[1].y;
  243.        face.tvlist[1].u0 = (int)rend_list->poly_ptrs[poly]->tvlist[1].u0;
  244.        face.tvlist[1].v0 = (int)rend_list->poly_ptrs[poly]->tvlist[1].v0;
  245.        face.tvlist[2].x = (int)rend_list->poly_ptrs[poly]->tvlist[2].x;
  246.        face.tvlist[2].y = (int)rend_list->poly_ptrs[poly]->tvlist[2].y;
  247.        face.tvlist[2].u0 = (int)rend_list->poly_ptrs[poly]->tvlist[2].u0;
  248.        face.tvlist[2].v0 = (int)rend_list->poly_ptrs[poly]->tvlist[2].v0;
  249.     
  250.        // assign the texture
  251.        face.texture = rend_list->poly_ptrs[poly]->texture;
  252.        
  253.        // is this a plain emissive texture?
  254.        if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  255.           {
  256.           // draw the textured triangle as emissive
  257.           Draw_Textured_Triangle16(&face, video_buffer, lpitch);
  258.           } // end if
  259.        else
  260.           {
  261.           // draw as flat shaded
  262.           face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
  263.           Draw_Textured_TriangleFS16(&face, video_buffer, lpitch);
  264.           } // end else
  265.        } // end if      
  266.     else
  267.     if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  268.         (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  269.        {
  270.        // draw the triangle with basic flat rasterizer
  271.        Draw_Triangle_2D2_16(rend_list->poly_ptrs[poly]->tvlist[0].x, rend_list->poly_ptrs[poly]->tvlist[0].y,
  272.                  rend_list->poly_ptrs[poly]->tvlist[1].x, rend_list->poly_ptrs[poly]->tvlist[1].y,
  273.              rend_list->poly_ptrs[poly]->tvlist[2].x, rend_list->poly_ptrs[poly]->tvlist[2].y,
  274.                  rend_list->poly_ptrs[poly]->lit_color[0], video_buffer, lpitch);
  275.        } // end if
  276.     else
  277.     if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  278.        {
  279.         // {andre take advantage of the data structures later..}
  280.         // set the vertices
  281.         face.tvlist[0].x  = (int)rend_list->poly_ptrs[poly]->tvlist[0].x;
  282.         face.tvlist[0].y  = (int)rend_list->poly_ptrs[poly]->tvlist[0].y;
  283.         face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
  284.         face.tvlist[1].x  = (int)rend_list->poly_ptrs[poly]->tvlist[1].x;
  285.         face.tvlist[1].y  = (int)rend_list->poly_ptrs[poly]->tvlist[1].y;
  286.         face.lit_color[1] = rend_list->poly_ptrs[poly]->lit_color[1];
  287.         face.tvlist[2].x  = (int)rend_list->poly_ptrs[poly]->tvlist[2].x;
  288.         face.tvlist[2].y  = (int)rend_list->poly_ptrs[poly]->tvlist[2].y;
  289.         face.lit_color[2] = rend_list->poly_ptrs[poly]->lit_color[2];
  290.     // draw the gouraud shaded triangle
  291.         Draw_Gouraud_Triangle16(&face, video_buffer, lpitch);
  292.        } // end if gouraud
  293.     } // end for poly
  294. } // end Draw_RENDERLIST4DV2_Solid16
  295. ///////////////////////////////////////////////////////////////
  296. void Draw_RENDERLIST4DV2_Solid(RENDERLIST4DV2_PTR rend_list, 
  297.                               UCHAR *video_buffer, 
  298.   int lpitch)
  299. {
  300. // 8-bit version
  301. // this function "executes" the render list or in other words
  302. // draws all the faces in the list, the function will call the 
  303. // proper rasterizer based on the lighting model of the polygons
  304. POLYF4DV2 face; // temp face used to render polygon
  305. // at this point, all we have is a list of polygons and it's time
  306. // to draw them
  307. for (int poly=0; poly < rend_list->num_polys; poly++)
  308.     {
  309.     // render this polygon if and only if it's not clipped, not culled,
  310.     // active, and visible, note however the concecpt of "backface" is 
  311.     // irrelevant in a wire frame engine though
  312.     if (!(rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_ACTIVE) ||
  313.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_CLIPPED ) ||
  314.          (rend_list->poly_ptrs[poly]->state & POLY4DV2_STATE_BACKFACE) )
  315.        continue; // move onto next poly
  316.     // need to test for textured first, since a textured poly can either
  317.     // be emissive, or flat shaded, hence we need to call different
  318.     // rasterizers    
  319.     if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  320.        {
  321.        // set the vertices
  322.        face.tvlist[0].x = (int)rend_list->poly_ptrs[poly]->tvlist[0].x;
  323.        face.tvlist[0].y = (int)rend_list->poly_ptrs[poly]->tvlist[0].y;
  324.        face.tvlist[0].u0 = (int)rend_list->poly_ptrs[poly]->tvlist[0].u0;
  325.        face.tvlist[0].v0 = (int)rend_list->poly_ptrs[poly]->tvlist[0].v0;
  326.        face.tvlist[1].x = (int)rend_list->poly_ptrs[poly]->tvlist[1].x;
  327.        face.tvlist[1].y = (int)rend_list->poly_ptrs[poly]->tvlist[1].y;
  328.        face.tvlist[1].u0 = (int)rend_list->poly_ptrs[poly]->tvlist[1].u0;
  329.        face.tvlist[1].v0 = (int)rend_list->poly_ptrs[poly]->tvlist[1].v0;
  330.        face.tvlist[2].x = (int)rend_list->poly_ptrs[poly]->tvlist[2].x;
  331.        face.tvlist[2].y = (int)rend_list->poly_ptrs[poly]->tvlist[2].y;
  332.        face.tvlist[2].u0 = (int)rend_list->poly_ptrs[poly]->tvlist[2].u0;
  333.        face.tvlist[2].v0 = (int)rend_list->poly_ptrs[poly]->tvlist[2].v0;
  334.     
  335.        // assign the texture
  336.        face.texture = rend_list->poly_ptrs[poly]->texture;
  337.        
  338.        // is this a plain emissive texture?
  339.        if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  340.           {
  341.           // draw the textured triangle as emissive
  342.           Draw_Textured_Triangle(&face, video_buffer, lpitch);
  343.           } // end if
  344.        else
  345.           {
  346.           // draw as flat shaded
  347.           face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
  348.           Draw_Textured_TriangleFS(&face, video_buffer, lpitch);
  349.           } // end else
  350.        } // end if      
  351.     else
  352.     if ((rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  353.         (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  354.        {
  355.        // draw the triangle with basic flat rasterizer
  356.        Draw_Triangle_2D2(rend_list->poly_ptrs[poly]->tvlist[0].x, rend_list->poly_ptrs[poly]->tvlist[0].y,
  357.                  rend_list->poly_ptrs[poly]->tvlist[1].x, rend_list->poly_ptrs[poly]->tvlist[1].y,
  358.              rend_list->poly_ptrs[poly]->tvlist[2].x, rend_list->poly_ptrs[poly]->tvlist[2].y,
  359.                  rend_list->poly_ptrs[poly]->lit_color[0], video_buffer, lpitch);
  360.        } // end if
  361.     else
  362.     if (rend_list->poly_ptrs[poly]->attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  363.        {
  364.         // {andre take advantage of the data structures later..}
  365.         // set the vertices
  366.         face.tvlist[0].x  = (int)rend_list->poly_ptrs[poly]->tvlist[0].x;
  367.         face.tvlist[0].y  = (int)rend_list->poly_ptrs[poly]->tvlist[0].y;
  368.         face.lit_color[0] = rend_list->poly_ptrs[poly]->lit_color[0];
  369.         face.tvlist[1].x  = (int)rend_list->poly_ptrs[poly]->tvlist[1].x;
  370.         face.tvlist[1].y  = (int)rend_list->poly_ptrs[poly]->tvlist[1].y;
  371.         face.lit_color[1] = rend_list->poly_ptrs[poly]->lit_color[1];
  372.         face.tvlist[2].x  = (int)rend_list->poly_ptrs[poly]->tvlist[2].x;
  373.         face.tvlist[2].y  = (int)rend_list->poly_ptrs[poly]->tvlist[2].y;
  374.         face.lit_color[2] = rend_list->poly_ptrs[poly]->lit_color[2];
  375.     // draw the gouraud shaded triangle
  376.         Draw_Gouraud_Triangle(&face, video_buffer, lpitch);
  377.        } // end if gouraud
  378.     } // end for poly
  379. } // end Draw_RENDERLIST4DV2_Solid
  380. /////////////////////////////////////////////////////////////////
  381. void Draw_OBJECT4DV2_Solid(OBJECT4DV2_PTR obj, 
  382.                             UCHAR *video_buffer, int lpitch)
  383.                      
  384. {
  385. // this function renders an object to the screen  in
  386. // 8 bit mode, it has no regard at all about hidden surface removal, 
  387. // etc. the function only exists as an easy way to render an object 
  388. // without converting it into polygons, the function assumes all 
  389. // coordinates are screen coordinates, but will perform 2D clipping
  390. POLYF4DV2 face; // temp face used to render polygon
  391. // at this point, all we have is a list of polygons and it's time
  392. // to draw them
  393. for (int poly=0; poly < obj->num_polys; poly++)
  394.     {
  395.     // render this polygon if and only if it's not clipped, not culled,
  396.     // active, and visible, note however the concecpt of "backface" is 
  397.     // irrelevant in a wire frame engine though
  398.     if (!(obj->plist[poly].state & POLY4DV2_STATE_ACTIVE) ||
  399.          (obj->plist[poly].state & POLY4DV2_STATE_CLIPPED ) ||
  400.          (obj->plist[poly].state & POLY4DV2_STATE_BACKFACE) )
  401.        continue; // move onto next poly
  402.     // extract vertex indices into master list, rember the polygons are 
  403.     // NOT self contained, but based on the vertex list stored in the object
  404.     // itself
  405.     int vindex_0 = obj->plist[poly].vert[0];
  406.     int vindex_1 = obj->plist[poly].vert[1];
  407.     int vindex_2 = obj->plist[poly].vert[2];
  408.      // need to test for textured first, since a textured poly can either
  409.     // be emissive, or flat shaded, hence we need to call different
  410.     // rasterizers    
  411.     if (obj->plist[poly].attr  & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  412.        {
  413.        // set the vertices
  414.        face.tvlist[0].x = (int)obj->vlist_trans[ vindex_0].x;
  415.        face.tvlist[0].y = (int)obj->vlist_trans[ vindex_0].y;
  416.        face.tvlist[0].u0 = (int)obj->vlist_trans[ vindex_0].u0;
  417.        face.tvlist[0].v0 = (int)obj->vlist_trans[ vindex_0].v0;
  418.        face.tvlist[1].x = (int)obj->vlist_trans[ vindex_1].x;
  419.        face.tvlist[1].y = (int)obj->vlist_trans[ vindex_1].y;
  420.        face.tvlist[1].u0 = (int)obj->vlist_trans[ vindex_1].u0;
  421.        face.tvlist[1].v0 = (int)obj->vlist_trans[ vindex_1].v0;
  422.        face.tvlist[2].x = (int)obj->vlist_trans[ vindex_2].x;
  423.        face.tvlist[2].y = (int)obj->vlist_trans[ vindex_2].y;
  424.        face.tvlist[2].u0 = (int)obj->vlist_trans[ vindex_2].u0;
  425.        face.tvlist[2].v0 = (int)obj->vlist_trans[ vindex_2].v0;
  426.     
  427.        // assign the texture
  428.        face.texture = obj->plist[poly].texture;
  429.        
  430.        // is this a plain emissive texture?
  431.        if (obj->plist[poly].attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  432.           {
  433.           // draw the textured triangle as emissive
  434.           Draw_Textured_Triangle(&face, video_buffer, lpitch);
  435.           } // end if
  436.        else
  437.           {
  438.           // draw as flat shaded
  439.           face.lit_color[0] = obj->plist[poly].lit_color[0];
  440.           Draw_Textured_TriangleFS(&face, video_buffer, lpitch);
  441.           } // end else
  442.        } // end if      
  443.     else
  444.     if ((obj->plist[poly].attr  & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  445.         (obj->plist[poly].attr  & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  446.        {
  447.        // draw the triangle with basic flat rasterizer
  448.        Draw_Triangle_2D2(obj->vlist_trans[ vindex_0].x, obj->vlist_trans[ vindex_0].y,
  449.                  obj->vlist_trans[ vindex_1].x, obj->vlist_trans[ vindex_1].y,
  450.              obj->vlist_trans[ vindex_2].x, obj->vlist_trans[ vindex_2].y,
  451.                  obj->plist[poly].lit_color[0], video_buffer, lpitch);
  452.        } // end if
  453.     else
  454.     if (obj->plist[poly].attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  455.        {
  456.         // {andre take advantage of the data structures later..}
  457.         // set the vertices
  458.         face.tvlist[0].x  = (int)obj->vlist_trans[ vindex_0].x;
  459.         face.tvlist[0].y  = (int)obj->vlist_trans[ vindex_0].y;
  460.         face.lit_color[0] = obj->plist[poly].lit_color[0];
  461.         face.tvlist[1].x  = (int)obj->vlist_trans[ vindex_1].x;
  462.         face.tvlist[1].y  = (int)obj->vlist_trans[ vindex_1].y;
  463.         face.lit_color[1] = obj->plist[poly].lit_color[1];
  464.         face.tvlist[2].x  = (int)obj->vlist_trans[ vindex_2].x;
  465.         face.tvlist[2].y  = (int)obj->vlist_trans[ vindex_2].y;
  466.         face.lit_color[2] = obj->plist[poly].lit_color[2];
  467.     
  468.        // draw the gouraud shaded triangle
  469.        Draw_Gouraud_Triangle(&face, video_buffer, lpitch);
  470.        } // end if gouraud
  471.     } // end for poly
  472. } // end Draw_OBJECT4DV2_Solid
  473. ///////////////////////////////////////////////////////////////
  474. void Draw_OBJECT4DV2_Solid16(OBJECT4DV2_PTR obj, 
  475.                             UCHAR *video_buffer, int lpitch)
  476.                      
  477. {
  478. // this function renders an object to the screen  in
  479. // 16 bit mode, it has no regard at all about hidden surface removal, 
  480. // etc. the function only exists as an easy way to render an object 
  481. // without converting it into polygons, the function assumes all 
  482. // coordinates are screen coordinates, but will perform 2D clipping
  483. POLYF4DV2 face; // temp face used to render polygon
  484. // at this point, all we have is a list of polygons and it's time
  485. // to draw them
  486. for (int poly=0; poly < obj->num_polys; poly++)
  487.     {
  488.     // render this polygon if and only if it's not clipped, not culled,
  489.     // active, and visible, note however the concecpt of "backface" is 
  490.     // irrelevant in a wire frame engine though
  491.     if (!(obj->plist[poly].state & POLY4DV2_STATE_ACTIVE) ||
  492.          (obj->plist[poly].state & POLY4DV2_STATE_CLIPPED ) ||
  493.          (obj->plist[poly].state & POLY4DV2_STATE_BACKFACE) )
  494.        continue; // move onto next poly
  495.     // extract vertex indices into master list, rember the polygons are 
  496.     // NOT self contained, but based on the vertex list stored in the object
  497.     // itself
  498.     int vindex_0 = obj->plist[poly].vert[0];
  499.     int vindex_1 = obj->plist[poly].vert[1];
  500.     int vindex_2 = obj->plist[poly].vert[2];
  501.  // need to test for textured first, since a textured poly can either
  502.     // be emissive, or flat shaded, hence we need to call different
  503.     // rasterizers    
  504.     if (obj->plist[poly].attr  & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
  505.        {
  506.        // set the vertices
  507.        face.tvlist[0].x = (int)obj->vlist_trans[ vindex_0].x;
  508.        face.tvlist[0].y = (int)obj->vlist_trans[ vindex_0].y;
  509.        face.tvlist[0].u0 = (int)obj->vlist_trans[ vindex_0].u0;
  510.        face.tvlist[0].v0 = (int)obj->vlist_trans[ vindex_0].v0;
  511.        face.tvlist[1].x = (int)obj->vlist_trans[ vindex_1].x;
  512.        face.tvlist[1].y = (int)obj->vlist_trans[ vindex_1].y;
  513.        face.tvlist[1].u0 = (int)obj->vlist_trans[ vindex_1].u0;
  514.        face.tvlist[1].v0 = (int)obj->vlist_trans[ vindex_1].v0;
  515.        face.tvlist[2].x = (int)obj->vlist_trans[ vindex_2].x;
  516.        face.tvlist[2].y = (int)obj->vlist_trans[ vindex_2].y;
  517.        face.tvlist[2].u0 = (int)obj->vlist_trans[ vindex_2].u0;
  518.        face.tvlist[2].v0 = (int)obj->vlist_trans[ vindex_2].v0;
  519.     
  520.        // assign the texture
  521.        face.texture = obj->plist[poly].texture;
  522.        
  523.        // is this a plain emissive texture?
  524.        if (obj->plist[poly].attr & POLY4DV2_ATTR_SHADE_MODE_CONSTANT)
  525.           {
  526.           // draw the textured triangle as emissive
  527.           Draw_Textured_Triangle16(&face, video_buffer, lpitch);
  528.           } // end if
  529.        else
  530.           {
  531.           // draw as flat shaded
  532.           face.lit_color[0] = obj->plist[poly].lit_color[0];
  533.           Draw_Textured_TriangleFS16(&face, video_buffer, lpitch);
  534.           } // end else
  535.        } // end if      
  536.     else
  537.     if ((obj->plist[poly].attr  & POLY4DV2_ATTR_SHADE_MODE_FLAT) || 
  538.         (obj->plist[poly].attr  & POLY4DV2_ATTR_SHADE_MODE_CONSTANT) )
  539.        {
  540.        // draw the triangle with basic flat rasterizer
  541.        Draw_Triangle_2D2_16(obj->vlist_trans[ vindex_0].x, obj->vlist_trans[ vindex_0].y,
  542.                  obj->vlist_trans[ vindex_1].x, obj->vlist_trans[ vindex_1].y,
  543.              obj->vlist_trans[ vindex_2].x, obj->vlist_trans[ vindex_2].y,
  544.                  obj->plist[poly].lit_color[0], video_buffer, lpitch);
  545.        } // end if
  546.     else
  547.     if (obj->plist[poly].attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD)
  548.        {
  549.         // {andre take advantage of the data structures later..}
  550.         // set the vertices
  551.         face.tvlist[0].x  = (int)obj->vlist_trans[ vindex_0].x;
  552.         face.tvlist[0].y  = (int)obj->vlist_trans[ vindex_0].y;
  553.         face.lit_color[0] = obj->plist[poly].lit_color[0];
  554.         face.tvlist[1].x  = (int)obj->vlist_trans[ vindex_1].x;
  555.         face.tvlist[1].y  = (int)obj->vlist_trans[ vindex_1].y;
  556.         face.lit_color[1] = obj->plist[poly].lit_color[1];
  557.         face.tvlist[2].x  = (int)obj->vlist_trans[ vindex_2].x;
  558.         face.tvlist[2].y  = (int)obj->vlist_trans[ vindex_2].y;
  559.         face.lit_color[2] = obj->plist[poly].lit_color[2];
  560.     
  561.        // draw the gouraud shaded triangle
  562.        Draw_Gouraud_Triangle16(&face, video_buffer, lpitch);
  563.        } // end if gouraud
  564.     } // end for poly
  565. } // end Draw_OBJECT4DV2_Solid16
  566. /////////////////////////////////////////////////////////////
  567. void Draw_Textured_Triangle(POLYF4DV2_PTR face,   // ptr to face
  568.                             UCHAR *dest_buffer,   // pointer to video buffer
  569.                             int mem_pitch)        // bytes per line, 320, 640 etc.
  570. {
  571. // this function draws a textured triangle in 8-bit mode
  572. int v0=0,
  573.     v1=1,
  574. v2=2,
  575. temp=0,
  576. tri_type = TRI_TYPE_NONE,
  577. irestart = INTERP_LHS;
  578. int dx,dy,dyl,dyr,          // general deltas
  579.     u,v,
  580.     du,dv,
  581.     xi,yi,                  // the current interpolated x,y
  582. ui,vi,              // the current interpolated u,v
  583. index_x,index_y,    // looping vars
  584. x,y,                // hold general x,y
  585. xstart,
  586. xend,
  587. ystart,
  588. yrestart,
  589. yend,
  590. xl,                 
  591. dxdyl,              
  592. xr,
  593. dxdyr,             
  594. dudyl,    
  595. ul,
  596. dvdyl,   
  597. vl,
  598. dudyr,
  599. ur,
  600. dvdyr,
  601. vr;
  602. int x0,y0,tu0,tv0,    // cached vertices
  603. x1,y1,tu1,tv1,
  604. x2,y2,tu2,tv2;
  605. UCHAR *screen_ptr  = NULL,
  606.   *screen_line = NULL,
  607.   *textmap     = NULL;
  608. #ifdef DEBUG_ON
  609. // track rendering stats
  610.     debug_polys_rendered_per_frame++;
  611. #endif
  612. // extract texture map
  613. textmap = face->texture->buffer;
  614. // extract base 2 of texture width
  615. int texture_shift2 = logbase2ofx[face->texture->width];
  616. // first trivial clipping rejection tests 
  617. if (((face->tvlist[0].y < min_clip_y)  && 
  618.  (face->tvlist[1].y < min_clip_y)  &&
  619.  (face->tvlist[2].y < min_clip_y)) ||
  620. ((face->tvlist[0].y > max_clip_y)  && 
  621.  (face->tvlist[1].y > max_clip_y)  &&
  622.  (face->tvlist[2].y > max_clip_y)) ||
  623. ((face->tvlist[0].x < min_clip_x)  && 
  624.  (face->tvlist[1].x < min_clip_x)  &&
  625.  (face->tvlist[2].x < min_clip_x)) ||
  626. ((face->tvlist[0].x > max_clip_x)  && 
  627.  (face->tvlist[1].x > max_clip_x)  &&
  628.  (face->tvlist[2].x > max_clip_x)))
  629.    return;
  630. // degenerate triangle
  631. if ( ((face->tvlist[0].x==face->tvlist[1].x) && (face->tvlist[1].x==face->tvlist[2].x)) ||
  632.  ((face->tvlist[0].y==face->tvlist[1].y) && (face->tvlist[1].y==face->tvlist[2].y)))
  633.    return;
  634. // sort vertices
  635. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  636. {SWAP(v0,v1,temp);} 
  637. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  638. {SWAP(v0,v2,temp);}
  639. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  640. {SWAP(v1,v2,temp);}
  641. // now test for trivial flat sided cases
  642. if (face->tvlist[v0].y==face->tvlist[v1].y)
  643. // set triangle type
  644. tri_type = TRI_TYPE_FLAT_TOP;
  645. // sort vertices left to right
  646. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  647. {SWAP(v0,v1,temp);}
  648. } // end if
  649. else
  650. // now test for trivial flat sided cases
  651. if (face->tvlist[v1].y==face->tvlist[v2].y)
  652. // set triangle type
  653. tri_type = TRI_TYPE_FLAT_BOTTOM;
  654. // sort vertices left to right
  655. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  656. {SWAP(v1,v2,temp);}
  657. } // end if
  658. else
  659. {
  660. // must be a general triangle
  661. tri_type = TRI_TYPE_GENERAL;
  662. } // end else
  663. // extract vertices for processing, now that we have order
  664. x0  = (int)(face->tvlist[v0].x+0.5);
  665. y0  = (int)(face->tvlist[v0].y+0.5);
  666. tu0 = (int)(face->tvlist[v0].u0);
  667. tv0 = (int)(face->tvlist[v0].v0);
  668. x1  = (int)(face->tvlist[v1].x+0.5);
  669. y1  = (int)(face->tvlist[v1].y+0.5);
  670. tu1 = (int)(face->tvlist[v1].u0);
  671. tv1 = (int)(face->tvlist[v1].v0);
  672. x2  = (int)(face->tvlist[v2].x+0.5);
  673. y2  = (int)(face->tvlist[v2].y+0.5);
  674. tu2 = (int)(face->tvlist[v2].u0);
  675. tv2 = (int)(face->tvlist[v2].v0);
  676. // set interpolation restart value
  677. yrestart = y1;
  678. // what kind of triangle
  679. if (tri_type & TRI_TYPE_FLAT_MASK)
  680. {
  681. if (tri_type == TRI_TYPE_FLAT_TOP)
  682. {
  683. // compute all deltas
  684. dy = (y2 - y0);
  685. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  686. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  687. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  688. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  689. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  690. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  691. // test for y clipping
  692. if (y0 < min_clip_y)
  693. {
  694. // compute overclip
  695. dy = (min_clip_y - y0);
  696. // computer new LHS starting values
  697. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  698. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  699. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  700. // compute new RHS starting values
  701. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  702. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  703. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  704. // compute new starting y
  705. ystart = min_clip_y;
  706. } // end if
  707. else
  708. {
  709. // no clipping
  710. // set starting values
  711. xl = (x0 << FIXP16_SHIFT);
  712. xr = (x1 << FIXP16_SHIFT);
  713. ul = (tu0 << FIXP16_SHIFT);
  714. vl = (tv0 << FIXP16_SHIFT);
  715. ur = (tu1 << FIXP16_SHIFT);
  716. vr = (tv1 << FIXP16_SHIFT);
  717. // set starting y
  718. ystart = y0;
  719. } // end else
  720. } // end if flat top
  721. else
  722. {
  723. // must be flat bottom
  724. // compute all deltas
  725. dy = (y1 - y0);
  726. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  727. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  728. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  729. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  730. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  731. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  732. // test for y clipping
  733. if (y0 < min_clip_y)
  734. {
  735. // compute overclip
  736. dy = (min_clip_y - y0);
  737. // computer new LHS starting values
  738. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  739. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  740. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  741. // compute new RHS starting values
  742. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  743. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  744. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  745. // compute new starting y
  746. ystart = min_clip_y;
  747. } // end if
  748. else
  749. {
  750. // no clipping
  751. // set starting values
  752. xl = (x0 << FIXP16_SHIFT);
  753. xr = (x0 << FIXP16_SHIFT);
  754. ul = (tu0 << FIXP16_SHIFT);
  755. vl = (tv0 << FIXP16_SHIFT);
  756. ur = (tu0 << FIXP16_SHIFT);
  757. vr = (tv0 << FIXP16_SHIFT);
  758. // set starting y
  759. ystart = y0;
  760. } // end else
  761. } // end else flat bottom
  762. // test for bottom clip, always
  763. if ((yend = y2) > max_clip_y)
  764. yend = max_clip_y;
  765.     // test for horizontal clipping
  766. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  767. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  768. (x2 < min_clip_x) || (x2 > max_clip_x))
  769. {
  770.     // clip version
  771. // point screen ptr to starting line
  772. screen_ptr = dest_buffer + (ystart * mem_pitch);
  773. for (yi = ystart; yi<=yend; yi++)
  774. {
  775. // compute span endpoints
  776. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  777. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  778. // compute starting points for u,v interpolants
  779. ui = ul + FIXP16_ROUND_UP;
  780. vi = vl + FIXP16_ROUND_UP;
  781. // compute u,v interpolants
  782. if ((dx = (xend - xstart))>0)
  783. {
  784. du = (ur - ul)/dx;
  785. dv = (vr - vl)/dx;
  786. } // end if
  787. else
  788. {
  789. du = (ur - ul);
  790. dv = (vr - vl);
  791. } // end else
  792. ///////////////////////////////////////////////////////////////////////
  793. // test for x clipping, LHS
  794. if (xstart < min_clip_x)
  795. {
  796. // compute x overlap
  797. dx = min_clip_x - xstart;
  798. // slide interpolants over
  799. ui+=dx*du;
  800. vi+=dx*dv;
  801. // reset vars
  802. xstart = min_clip_x;
  803. } // end if
  804. // test for x clipping RHS
  805. if (xend > max_clip_x)
  806. xend = max_clip_x;
  807. ///////////////////////////////////////////////////////////////////////
  808. // draw span
  809. for (xi=xstart; xi<=xend; xi++)
  810. {
  811. // write textel
  812.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  813. // interpolate u,v
  814. ui+=du;
  815. vi+=dv;
  816. } // end for xi
  817. // interpolate u,v,x along right and left edge
  818. xl+=dxdyl;
  819. ul+=dudyl;
  820. vl+=dvdyl;
  821. xr+=dxdyr;
  822. ur+=dudyr;
  823. vr+=dvdyr;
  824.  
  825. // advance screen ptr
  826. screen_ptr+=mem_pitch;
  827. } // end for y
  828. } // end if clip
  829. else
  830. {
  831. // non-clip version
  832. // point screen ptr to starting line
  833. screen_ptr = dest_buffer + (ystart * mem_pitch);
  834. for (yi = ystart; yi<=yend; yi++)
  835. {
  836. // compute span endpoints
  837. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  838. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  839. // compute starting points for u,v interpolants
  840. ui = ul + FIXP16_ROUND_UP;
  841. vi = vl + FIXP16_ROUND_UP;
  842. // compute u,v interpolants
  843. if ((dx = (xend - xstart))>0)
  844. {
  845. du = (ur - ul)/dx;
  846. dv = (vr - vl)/dx;
  847. } // end if
  848. else
  849. {
  850. du = (ur - ul);
  851. dv = (vr - vl);
  852. } // end else
  853. // draw span
  854. for (xi=xstart; xi<=xend; xi++)
  855. {
  856. // write textel
  857.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  858. // interpolate u,v
  859. ui+=du;
  860. vi+=dv;
  861. } // end for xi
  862. // interpolate u,v,x along right and left edge
  863. xl+=dxdyl;
  864. ul+=dudyl;
  865. vl+=dvdyl;
  866. xr+=dxdyr;
  867. ur+=dudyr;
  868. vr+=dvdyr;
  869. // advance screen ptr
  870. screen_ptr+=mem_pitch;
  871. } // end for y
  872. } // end if non-clipped
  873. } // end if
  874. else
  875. if (tri_type==TRI_TYPE_GENERAL)
  876. {
  877. // first test for bottom clip, always
  878. if ((yend = y2) > max_clip_y)
  879. yend = max_clip_y;
  880. // pre-test y clipping status
  881. if (y1 < min_clip_y)
  882. {
  883. // compute all deltas
  884. // LHS
  885. dyl = (y2 - y1);
  886. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  887. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  888. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  889. // RHS
  890. dyr = (y2 - y0);
  891. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  892. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  893. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  894. // compute overclip
  895. dyr = (min_clip_y - y0);
  896. dyl = (min_clip_y - y1);
  897. // computer new LHS starting values
  898. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  899. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  900. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  901. // compute new RHS starting values
  902. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  903. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  904. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  905. // compute new starting y
  906. ystart = min_clip_y;
  907. // test if we need swap to keep rendering left to right
  908. if (dxdyr > dxdyl)
  909. {
  910. SWAP(dxdyl,dxdyr,temp);
  911. SWAP(dudyl,dudyr,temp);
  912. SWAP(dvdyl,dvdyr,temp);
  913. SWAP(xl,xr,temp);
  914. SWAP(ul,ur,temp);
  915. SWAP(vl,vr,temp);
  916. SWAP(x1,x2,temp);
  917. SWAP(y1,y2,temp);
  918. SWAP(tu1,tu2,temp);
  919. SWAP(tv1,tv2,temp);
  920. // set interpolation restart
  921. irestart = INTERP_RHS;
  922. } // end if
  923. } // end if
  924. else
  925. if (y0 < min_clip_y)
  926. {
  927. // compute all deltas
  928. // LHS
  929. dyl = (y1 - y0);
  930. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  931. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  932. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  933. // RHS
  934. dyr = (y2 - y0);
  935. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  936. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  937. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  938. // compute overclip
  939. dy = (min_clip_y - y0);
  940. // computer new LHS starting values
  941. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  942. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  943. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  944. // compute new RHS starting values
  945. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  946. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  947. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  948. // compute new starting y
  949. ystart = min_clip_y;
  950. // test if we need swap to keep rendering left to right
  951. if (dxdyr < dxdyl)
  952. {
  953. SWAP(dxdyl,dxdyr,temp);
  954. SWAP(dudyl,dudyr,temp);
  955. SWAP(dvdyl,dvdyr,temp);
  956. SWAP(xl,xr,temp);
  957. SWAP(ul,ur,temp);
  958. SWAP(vl,vr,temp);
  959. SWAP(x1,x2,temp);
  960. SWAP(y1,y2,temp);
  961. SWAP(tu1,tu2,temp);
  962. SWAP(tv1,tv2,temp);
  963. // set interpolation restart
  964. irestart = INTERP_RHS;
  965. } // end if
  966. } // end if
  967. else
  968. {
  969. // no initial y clipping
  970. // compute all deltas
  971. // LHS
  972. dyl = (y1 - y0);
  973. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  974. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  975. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  976. // RHS
  977. dyr = (y2 - y0);
  978. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  979. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  980. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  981. // no clipping y
  982. // set starting values
  983. xl = (x0 << FIXP16_SHIFT);
  984. xr = (x0 << FIXP16_SHIFT);
  985. ul = (tu0 << FIXP16_SHIFT);
  986. vl = (tv0 << FIXP16_SHIFT);
  987. ur = (tu0 << FIXP16_SHIFT);
  988. vr = (tv0 << FIXP16_SHIFT);
  989. // set starting y
  990. ystart = y0;
  991. // test if we need swap to keep rendering left to right
  992. if (dxdyr < dxdyl)
  993. {
  994. SWAP(dxdyl,dxdyr,temp);
  995. SWAP(dudyl,dudyr,temp);
  996. SWAP(dvdyl,dvdyr,temp);
  997. SWAP(xl,xr,temp);
  998. SWAP(ul,ur,temp);
  999. SWAP(vl,vr,temp);
  1000. SWAP(x1,x2,temp);
  1001. SWAP(y1,y2,temp);
  1002. SWAP(tu1,tu2,temp);
  1003. SWAP(tv1,tv2,temp);
  1004. // set interpolation restart
  1005. irestart = INTERP_RHS;
  1006. } // end if
  1007. } // end else
  1008.     // test for horizontal clipping
  1009. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1010. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1011. (x2 < min_clip_x) || (x2 > max_clip_x))
  1012. {
  1013.     // clip version
  1014. // x clipping
  1015. // point screen ptr to starting line
  1016. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1017. for (yi = ystart; yi<=yend; yi++)
  1018. {
  1019. // compute span endpoints
  1020. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1021. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1022. // compute starting points for u,v interpolants
  1023. ui = ul + FIXP16_ROUND_UP;
  1024. vi = vl + FIXP16_ROUND_UP;
  1025. // compute u,v interpolants
  1026. if ((dx = (xend - xstart))>0)
  1027. {
  1028. du = (ur - ul)/dx;
  1029. dv = (vr - vl)/dx;
  1030. } // end if
  1031. else
  1032. {
  1033. du = (ur - ul);
  1034. dv = (vr - vl);
  1035. } // end else
  1036. ///////////////////////////////////////////////////////////////////////
  1037. // test for x clipping, LHS
  1038. if (xstart < min_clip_x)
  1039. {
  1040. // compute x overlap
  1041. dx = min_clip_x - xstart;
  1042. // slide interpolants over
  1043. ui+=dx*du;
  1044. vi+=dx*dv;
  1045. // set x to left clip edge
  1046. xstart = min_clip_x;
  1047. } // end if
  1048. // test for x clipping RHS
  1049. if (xend > max_clip_x)
  1050. xend = max_clip_x;
  1051. ///////////////////////////////////////////////////////////////////////
  1052. // draw span
  1053. for (xi=xstart; xi<=xend; xi++)
  1054. {
  1055. // write textel
  1056.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1057. // interpolate u,v
  1058. ui+=du;
  1059. vi+=dv;
  1060. } // end for xi
  1061. // interpolate u,v,x along right and left edge
  1062. xl+=dxdyl;
  1063. ul+=dudyl;
  1064. vl+=dvdyl;
  1065. xr+=dxdyr;
  1066. ur+=dudyr;
  1067. vr+=dvdyr;
  1068. // advance screen ptr
  1069. screen_ptr+=mem_pitch;
  1070. // test for yi hitting second region, if so change interpolant
  1071. if (yi==yrestart)
  1072. {
  1073. // test interpolation side change flag
  1074. if (irestart == INTERP_LHS)
  1075. {
  1076. // LHS
  1077. dyl = (y2 - y1);
  1078. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1079. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1080. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1081. // set starting values
  1082. xl = (x1  << FIXP16_SHIFT);
  1083. ul = (tu1 << FIXP16_SHIFT);
  1084. vl = (tv1 << FIXP16_SHIFT);
  1085. // interpolate down on LHS to even up
  1086. xl+=dxdyl;
  1087. ul+=dudyl;
  1088. vl+=dvdyl;
  1089. } // end if
  1090. else
  1091. {
  1092. // RHS
  1093. dyr = (y1 - y2);
  1094. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1095. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1096. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1097. // set starting values
  1098. xr = (x2  << FIXP16_SHIFT);
  1099. ur = (tu2 << FIXP16_SHIFT);
  1100. vr = (tv2 << FIXP16_SHIFT);
  1101. // interpolate down on RHS to even up
  1102. xr+=dxdyr;
  1103. ur+=dudyr;
  1104. vr+=dvdyr;
  1105. } // end else
  1106. } // end if
  1107. } // end for y
  1108. } // end if
  1109. else
  1110. {
  1111. // no x clipping
  1112. // point screen ptr to starting line
  1113. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1114. for (yi = ystart; yi<=yend; yi++)
  1115. {
  1116. // compute span endpoints
  1117. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1118. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1119. // compute starting points for u,v interpolants
  1120. ui = ul + FIXP16_ROUND_UP;
  1121. vi = vl + FIXP16_ROUND_UP;
  1122. // compute u,v interpolants
  1123. if ((dx = (xend - xstart))>0)
  1124. {
  1125. du = (ur - ul)/dx;
  1126. dv = (vr - vl)/dx;
  1127. } // end if
  1128. else
  1129. {
  1130. du = (ur - ul);
  1131. dv = (vr - vl);
  1132. } // end else
  1133. // draw span
  1134. for (xi=xstart; xi<=xend; xi++)
  1135. {
  1136. // write textel
  1137.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1138. // interpolate u,v
  1139. ui+=du;
  1140. vi+=dv;
  1141. } // end for xi
  1142. // interpolate u,v,x along right and left edge
  1143. xl+=dxdyl;
  1144. ul+=dudyl;
  1145. vl+=dvdyl;
  1146. xr+=dxdyr;
  1147. ur+=dudyr;
  1148. vr+=dvdyr;
  1149. // advance screen ptr
  1150. screen_ptr+=mem_pitch;
  1151. // test for yi hitting second region, if so change interpolant
  1152. if (yi==yrestart)
  1153. {
  1154. // test interpolation side change flag
  1155. if (irestart == INTERP_LHS)
  1156. {
  1157. // LHS
  1158. dyl = (y2 - y1);
  1159. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1160. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1161. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1162. // set starting values
  1163. xl = (x1  << FIXP16_SHIFT);
  1164. ul = (tu1 << FIXP16_SHIFT);
  1165. vl = (tv1 << FIXP16_SHIFT);
  1166. // interpolate down on LHS to even up
  1167. xl+=dxdyl;
  1168. ul+=dudyl;
  1169. vl+=dvdyl;
  1170. } // end if
  1171. else
  1172. {
  1173. // RHS
  1174. dyr = (y1 - y2);
  1175. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1176. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1177. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1178. // set starting values
  1179. xr = (x2  << FIXP16_SHIFT);
  1180. ur = (tu2 << FIXP16_SHIFT);
  1181. vr = (tv2 << FIXP16_SHIFT);
  1182. // interpolate down on RHS to even up
  1183. xr+=dxdyr;
  1184. ur+=dudyr;
  1185. vr+=dvdyr;
  1186. } // end else
  1187. } // end if
  1188. } // end for y
  1189. } // end else
  1190. } // end if
  1191. } // end Draw_Textured_Triangle
  1192. //////////////////////////////////////////////////////////////////////
  1193. void Draw_Textured_TriangleFS(POLYF4DV2_PTR face,   // ptr to face
  1194.                             UCHAR *dest_buffer,   // pointer to video buffer
  1195.                             int mem_pitch)        // bytes per line, 320, 640 etc.
  1196. {
  1197. // this function draws a textured triangle in 8-bit mode
  1198. int v0=0,
  1199.     v1=1,
  1200. v2=2,
  1201. temp=0,
  1202. tri_type = TRI_TYPE_NONE,
  1203. irestart = INTERP_LHS;
  1204. int dx,dy,dyl,dyr,          // general deltas
  1205.     u,v,
  1206.     du,dv,
  1207.     xi,yi,                  // the current interpolated x,y
  1208. ui,vi,              // the current interpolated u,v
  1209. index_x,index_y,    // looping vars
  1210. x,y,                // hold general x,y
  1211. xstart,
  1212. xend,
  1213. ystart,
  1214. yrestart,
  1215. yend,
  1216. xl,                 
  1217. dxdyl,              
  1218. xr,
  1219. dxdyr,             
  1220. dudyl,    
  1221. ul,
  1222. dvdyl,   
  1223. vl,
  1224. dudyr,
  1225. ur,
  1226. dvdyr,
  1227. vr;
  1228. int x0,y0,tu0,tv0,    // cached vertices
  1229. x1,y1,tu1,tv1,
  1230. x2,y2,tu2,tv2;
  1231. int r_base, g_base, b_base, base_rgb444, textel; // used for color modulation algorithm to light texture
  1232. UCHAR *screen_ptr    = NULL,
  1233.   *screen_line   = NULL,
  1234.   *textmap       = NULL,
  1235.       *lightrow444_8 = NULL;
  1236. #ifdef DEBUG_ON
  1237. // track rendering stats
  1238.     debug_polys_rendered_per_frame++;
  1239. #endif
  1240. // extract texture map
  1241. textmap = face->texture->buffer;
  1242. // extract base 2 of texture width
  1243. int texture_shift2 = logbase2ofx[face->texture->width];
  1244. // first trivial clipping rejection tests 
  1245. if (((face->tvlist[0].y < min_clip_y)  && 
  1246.  (face->tvlist[1].y < min_clip_y)  &&
  1247.  (face->tvlist[2].y < min_clip_y)) ||
  1248. ((face->tvlist[0].y > max_clip_y)  && 
  1249.  (face->tvlist[1].y > max_clip_y)  &&
  1250.  (face->tvlist[2].y > max_clip_y)) ||
  1251. ((face->tvlist[0].x < min_clip_x)  && 
  1252.  (face->tvlist[1].x < min_clip_x)  &&
  1253.  (face->tvlist[2].x < min_clip_x)) ||
  1254. ((face->tvlist[0].x > max_clip_x)  && 
  1255.  (face->tvlist[1].x > max_clip_x)  &&
  1256.  (face->tvlist[2].x > max_clip_x)))
  1257.    return;
  1258. // degenerate triangle
  1259. if ( ((face->tvlist[0].x==face->tvlist[1].x) && (face->tvlist[1].x==face->tvlist[2].x)) ||
  1260.  ((face->tvlist[0].y==face->tvlist[1].y) && (face->tvlist[1].y==face->tvlist[2].y)))
  1261.    return;
  1262. // sort vertices
  1263. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  1264. {SWAP(v0,v1,temp);} 
  1265. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  1266. {SWAP(v0,v2,temp);}
  1267. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  1268. {SWAP(v1,v2,temp);}
  1269. // now test for trivial flat sided cases
  1270. if (face->tvlist[v0].y==face->tvlist[v1].y)
  1271. // set triangle type
  1272. tri_type = TRI_TYPE_FLAT_TOP;
  1273. // sort vertices left to right
  1274. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  1275. {SWAP(v0,v1,temp);}
  1276. } // end if
  1277. else
  1278. // now test for trivial flat sided cases
  1279. if (face->tvlist[v1].y==face->tvlist[v2].y)
  1280. // set triangle type
  1281. tri_type = TRI_TYPE_FLAT_BOTTOM;
  1282. // sort vertices left to right
  1283. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  1284. {SWAP(v1,v2,temp);}
  1285. } // end if
  1286. else
  1287. {
  1288. // must be a general triangle
  1289. tri_type = TRI_TYPE_GENERAL;
  1290. } // end else
  1291. // extract base color of lit poly, so we can modulate texture a bit
  1292. // for lighting
  1293. r_base = palette[face->lit_color[0]].peRed;
  1294. g_base = palette[face->lit_color[0]].peGreen;
  1295. b_base = palette[face->lit_color[0]].peBlue;
  1296. // build 4.4.4 intensity for color modulation
  1297. base_rgb444 = ( (b_base >> 4) + ((g_base >> 4) << 4) + ((r_base >> 4) << 8) );
  1298. // now find row in light table we will need for the r,g,b values on this polygon
  1299. lightrow444_8 = rgblightlookup[base_rgb444];
  1300. // extract vertices for processing, now that we have order
  1301. x0  = (int)(face->tvlist[v0].x+0.5);
  1302. y0  = (int)(face->tvlist[v0].y+0.5);
  1303. tu0 = (int)(face->tvlist[v0].u0);
  1304. tv0 = (int)(face->tvlist[v0].v0);
  1305. x1  = (int)(face->tvlist[v1].x+0.5);
  1306. y1  = (int)(face->tvlist[v1].y+0.5);
  1307. tu1 = (int)(face->tvlist[v1].u0);
  1308. tv1 = (int)(face->tvlist[v1].v0);
  1309. x2  = (int)(face->tvlist[v2].x+0.5);
  1310. y2  = (int)(face->tvlist[v2].y+0.5);
  1311. tu2 = (int)(face->tvlist[v2].u0);
  1312. tv2 = (int)(face->tvlist[v2].v0);
  1313. // set interpolation restart value
  1314. yrestart = y1;
  1315. // what kind of triangle
  1316. if (tri_type & TRI_TYPE_FLAT_MASK)
  1317. {
  1318. if (tri_type == TRI_TYPE_FLAT_TOP)
  1319. {
  1320. // compute all deltas
  1321. dy = (y2 - y0);
  1322. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1323. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1324. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  1325. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  1326. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  1327. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  1328. // test for y clipping
  1329. if (y0 < min_clip_y)
  1330. {
  1331. // compute overclip
  1332. dy = (min_clip_y - y0);
  1333. // computer new LHS starting values
  1334. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1335. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1336. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1337. // compute new RHS starting values
  1338. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  1339. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  1340. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  1341. // compute new starting y
  1342. ystart = min_clip_y;
  1343. } // end if
  1344. else
  1345. {
  1346. // no clipping
  1347. // set starting values
  1348. xl = (x0 << FIXP16_SHIFT);
  1349. xr = (x1 << FIXP16_SHIFT);
  1350. ul = (tu0 << FIXP16_SHIFT);
  1351. vl = (tv0 << FIXP16_SHIFT);
  1352. ur = (tu1 << FIXP16_SHIFT);
  1353. vr = (tv1 << FIXP16_SHIFT);
  1354. // set starting y
  1355. ystart = y0;
  1356. } // end else
  1357. } // end if flat top
  1358. else
  1359. {
  1360. // must be flat bottom
  1361. // compute all deltas
  1362. dy = (y1 - y0);
  1363. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  1364. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  1365. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  1366. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1367. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1368. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  1369. // test for y clipping
  1370. if (y0 < min_clip_y)
  1371. {
  1372. // compute overclip
  1373. dy = (min_clip_y - y0);
  1374. // computer new LHS starting values
  1375. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1376. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1377. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1378. // compute new RHS starting values
  1379. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1380. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1381. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1382. // compute new starting y
  1383. ystart = min_clip_y;
  1384. } // end if
  1385. else
  1386. {
  1387. // no clipping
  1388. // set starting values
  1389. xl = (x0 << FIXP16_SHIFT);
  1390. xr = (x0 << FIXP16_SHIFT);
  1391. ul = (tu0 << FIXP16_SHIFT);
  1392. vl = (tv0 << FIXP16_SHIFT);
  1393. ur = (tu0 << FIXP16_SHIFT);
  1394. vr = (tv0 << FIXP16_SHIFT);
  1395. // set starting y
  1396. ystart = y0;
  1397. } // end else
  1398. } // end else flat bottom
  1399. // test for bottom clip, always
  1400. if ((yend = y2) > max_clip_y)
  1401. yend = max_clip_y;
  1402.     // test for horizontal clipping
  1403. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1404. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1405. (x2 < min_clip_x) || (x2 > max_clip_x))
  1406. {
  1407.     // clip version
  1408. // point screen ptr to starting line
  1409. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1410. for (yi = ystart; yi<=yend; yi++)
  1411. {
  1412. // compute span endpoints
  1413. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1414. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1415. // compute starting points for u,v interpolants
  1416. ui = ul + FIXP16_ROUND_UP;
  1417. vi = vl + FIXP16_ROUND_UP;
  1418. // compute u,v interpolants
  1419. if ((dx = (xend - xstart))>0)
  1420. {
  1421. du = (ur - ul)/dx;
  1422. dv = (vr - vl)/dx;
  1423. } // end if
  1424. else
  1425. {
  1426. du = (ur - ul);
  1427. dv = (vr - vl);
  1428. } // end else
  1429. ///////////////////////////////////////////////////////////////////////
  1430. // test for x clipping, LHS
  1431. if (xstart < min_clip_x)
  1432. {
  1433. // compute x overlap
  1434. dx = min_clip_x - xstart;
  1435. // slide interpolants over
  1436. ui+=dx*du;
  1437. vi+=dx*dv;
  1438. // reset vars
  1439. xstart = min_clip_x;
  1440. } // end if
  1441. // test for x clipping RHS
  1442. if (xend > max_clip_x)
  1443. xend = max_clip_x;
  1444. ///////////////////////////////////////////////////////////////////////
  1445. // draw span
  1446. for (xi=xstart; xi<=xend; xi++)
  1447. {
  1448. // write textel
  1449.             // get textel
  1450.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1451.             // modulate with base color via light table and write textel
  1452.             screen_ptr[xi] = lightrow444_8[textel];
  1453. // interpolate u,v
  1454. ui+=du;
  1455. vi+=dv;
  1456. } // end for xi
  1457. // interpolate u,v,x along right and left edge
  1458. xl+=dxdyl;
  1459. ul+=dudyl;
  1460. vl+=dvdyl;
  1461. xr+=dxdyr;
  1462. ur+=dudyr;
  1463. vr+=dvdyr;
  1464.  
  1465. // advance screen ptr
  1466. screen_ptr+=mem_pitch;
  1467. } // end for y
  1468. } // end if clip
  1469. else
  1470. {
  1471. // non-clip version
  1472. // point screen ptr to starting line
  1473. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1474. for (yi = ystart; yi<=yend; yi++)
  1475. {
  1476. // compute span endpoints
  1477. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1478. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1479. // compute starting points for u,v interpolants
  1480. ui = ul + FIXP16_ROUND_UP;
  1481. vi = vl + FIXP16_ROUND_UP;
  1482. // compute u,v interpolants
  1483. if ((dx = (xend - xstart))>0)
  1484. {
  1485. du = (ur - ul)/dx;
  1486. dv = (vr - vl)/dx;
  1487. } // end if
  1488. else
  1489. {
  1490. du = (ur - ul);
  1491. dv = (vr - vl);
  1492. } // end else
  1493. // draw span
  1494. for (xi=xstart; xi<=xend; xi++)
  1495. {
  1496. // write textel
  1497. // get textel
  1498.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1499.             // modulate with base color via light table and write textel
  1500.             screen_ptr[xi] = lightrow444_8[textel];
  1501. // interpolate u,v
  1502. ui+=du;
  1503. vi+=dv;
  1504. } // end for xi
  1505. // interpolate u,v,x along right and left edge
  1506. xl+=dxdyl;
  1507. ul+=dudyl;
  1508. vl+=dvdyl;
  1509. xr+=dxdyr;
  1510. ur+=dudyr;
  1511. vr+=dvdyr;
  1512. // advance screen ptr
  1513. screen_ptr+=mem_pitch;
  1514. } // end for y
  1515. } // end if non-clipped
  1516. } // end if
  1517. else
  1518. if (tri_type==TRI_TYPE_GENERAL)
  1519. {
  1520. // first test for bottom clip, always
  1521. if ((yend = y2) > max_clip_y)
  1522. yend = max_clip_y;
  1523. // pre-test y clipping status
  1524. if (y1 < min_clip_y)
  1525. {
  1526. // compute all deltas
  1527. // LHS
  1528. dyl = (y2 - y1);
  1529. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  1530. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1531. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  1532. // RHS
  1533. dyr = (y2 - y0);
  1534. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1535. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1536. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1537. // compute overclip
  1538. dyr = (min_clip_y - y0);
  1539. dyl = (min_clip_y - y1);
  1540. // computer new LHS starting values
  1541. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  1542. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  1543. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  1544. // compute new RHS starting values
  1545. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  1546. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  1547. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  1548. // compute new starting y
  1549. ystart = min_clip_y;
  1550. // test if we need swap to keep rendering left to right
  1551. if (dxdyr > dxdyl)
  1552. {
  1553. SWAP(dxdyl,dxdyr,temp);
  1554. SWAP(dudyl,dudyr,temp);
  1555. SWAP(dvdyl,dvdyr,temp);
  1556. SWAP(xl,xr,temp);
  1557. SWAP(ul,ur,temp);
  1558. SWAP(vl,vr,temp);
  1559. SWAP(x1,x2,temp);
  1560. SWAP(y1,y2,temp);
  1561. SWAP(tu1,tu2,temp);
  1562. SWAP(tv1,tv2,temp);
  1563. // set interpolation restart
  1564. irestart = INTERP_RHS;
  1565. } // end if
  1566. } // end if
  1567. else
  1568. if (y0 < min_clip_y)
  1569. {
  1570. // compute all deltas
  1571. // LHS
  1572. dyl = (y1 - y0);
  1573. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1574. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1575. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1576. // RHS
  1577. dyr = (y2 - y0);
  1578. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  1579. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1580. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1581. // compute overclip
  1582. dy = (min_clip_y - y0);
  1583. // computer new LHS starting values
  1584. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1585. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1586. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1587. // compute new RHS starting values
  1588. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  1589. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  1590. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  1591. // compute new starting y
  1592. ystart = min_clip_y;
  1593. // test if we need swap to keep rendering left to right
  1594. if (dxdyr < dxdyl)
  1595. {
  1596. SWAP(dxdyl,dxdyr,temp);
  1597. SWAP(dudyl,dudyr,temp);
  1598. SWAP(dvdyl,dvdyr,temp);
  1599. SWAP(xl,xr,temp);
  1600. SWAP(ul,ur,temp);
  1601. SWAP(vl,vr,temp);
  1602. SWAP(x1,x2,temp);
  1603. SWAP(y1,y2,temp);
  1604. SWAP(tu1,tu2,temp);
  1605. SWAP(tv1,tv2,temp);
  1606. // set interpolation restart
  1607. irestart = INTERP_RHS;
  1608. } // end if
  1609. } // end if
  1610. else
  1611. {
  1612. // no initial y clipping
  1613. // compute all deltas
  1614. // LHS
  1615. dyl = (y1 - y0);
  1616. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  1617. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  1618. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  1619. // RHS
  1620. dyr = (y2 - y0);
  1621. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  1622. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  1623. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  1624. // no clipping y
  1625. // set starting values
  1626. xl = (x0 << FIXP16_SHIFT);
  1627. xr = (x0 << FIXP16_SHIFT);
  1628. ul = (tu0 << FIXP16_SHIFT);
  1629. vl = (tv0 << FIXP16_SHIFT);
  1630. ur = (tu0 << FIXP16_SHIFT);
  1631. vr = (tv0 << FIXP16_SHIFT);
  1632. // set starting y
  1633. ystart = y0;
  1634. // test if we need swap to keep rendering left to right
  1635. if (dxdyr < dxdyl)
  1636. {
  1637. SWAP(dxdyl,dxdyr,temp);
  1638. SWAP(dudyl,dudyr,temp);
  1639. SWAP(dvdyl,dvdyr,temp);
  1640. SWAP(xl,xr,temp);
  1641. SWAP(ul,ur,temp);
  1642. SWAP(vl,vr,temp);
  1643. SWAP(x1,x2,temp);
  1644. SWAP(y1,y2,temp);
  1645. SWAP(tu1,tu2,temp);
  1646. SWAP(tv1,tv2,temp);
  1647. // set interpolation restart
  1648. irestart = INTERP_RHS;
  1649. } // end if
  1650. } // end else
  1651.     // test for horizontal clipping
  1652. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  1653. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  1654. (x2 < min_clip_x) || (x2 > max_clip_x))
  1655. {
  1656.     // clip version
  1657. // x clipping
  1658. // point screen ptr to starting line
  1659. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1660. for (yi = ystart; yi<=yend; yi++)
  1661. {
  1662. // compute span endpoints
  1663. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1664. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1665. // compute starting points for u,v interpolants
  1666. ui = ul + FIXP16_ROUND_UP;
  1667. vi = vl + FIXP16_ROUND_UP;
  1668. // compute u,v interpolants
  1669. if ((dx = (xend - xstart))>0)
  1670. {
  1671. du = (ur - ul)/dx;
  1672. dv = (vr - vl)/dx;
  1673. } // end if
  1674. else
  1675. {
  1676. du = (ur - ul);
  1677. dv = (vr - vl);
  1678. } // end else
  1679. ///////////////////////////////////////////////////////////////////////
  1680. // test for x clipping, LHS
  1681. if (xstart < min_clip_x)
  1682. {
  1683. // compute x overlap
  1684. dx = min_clip_x - xstart;
  1685. // slide interpolants over
  1686. ui+=dx*du;
  1687. vi+=dx*dv;
  1688. // set x to left clip edge
  1689. xstart = min_clip_x;
  1690. } // end if
  1691. // test for x clipping RHS
  1692. if (xend > max_clip_x)
  1693. xend = max_clip_x;
  1694. ///////////////////////////////////////////////////////////////////////
  1695. // draw span
  1696. for (xi=xstart; xi<=xend; xi++)
  1697. {
  1698. // write textel
  1699.             // get textel
  1700.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1701.             // modulate with base color via light table and write textel
  1702.             screen_ptr[xi] = lightrow444_8[textel];
  1703. // interpolate u,v
  1704. ui+=du;
  1705. vi+=dv;
  1706. } // end for xi
  1707. // interpolate u,v,x along right and left edge
  1708. xl+=dxdyl;
  1709. ul+=dudyl;
  1710. vl+=dvdyl;
  1711. xr+=dxdyr;
  1712. ur+=dudyr;
  1713. vr+=dvdyr;
  1714. // advance screen ptr
  1715. screen_ptr+=mem_pitch;
  1716. // test for yi hitting second region, if so change interpolant
  1717. if (yi==yrestart)
  1718. {
  1719. // test interpolation side change flag
  1720. if (irestart == INTERP_LHS)
  1721. {
  1722. // LHS
  1723. dyl = (y2 - y1);
  1724. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1725. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1726. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1727. // set starting values
  1728. xl = (x1  << FIXP16_SHIFT);
  1729. ul = (tu1 << FIXP16_SHIFT);
  1730. vl = (tv1 << FIXP16_SHIFT);
  1731. // interpolate down on LHS to even up
  1732. xl+=dxdyl;
  1733. ul+=dudyl;
  1734. vl+=dvdyl;
  1735. } // end if
  1736. else
  1737. {
  1738. // RHS
  1739. dyr = (y1 - y2);
  1740. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1741. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1742. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1743. // set starting values
  1744. xr = (x2  << FIXP16_SHIFT);
  1745. ur = (tu2 << FIXP16_SHIFT);
  1746. vr = (tv2 << FIXP16_SHIFT);
  1747. // interpolate down on RHS to even up
  1748. xr+=dxdyr;
  1749. ur+=dudyr;
  1750. vr+=dvdyr;
  1751. } // end else
  1752. } // end if
  1753. } // end for y
  1754. } // end if
  1755. else
  1756. {
  1757. // no x clipping
  1758. // point screen ptr to starting line
  1759. screen_ptr = dest_buffer + (ystart * mem_pitch);
  1760. for (yi = ystart; yi<=yend; yi++)
  1761. {
  1762. // compute span endpoints
  1763. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1764. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  1765. // compute starting points for u,v interpolants
  1766. ui = ul + FIXP16_ROUND_UP;
  1767. vi = vl + FIXP16_ROUND_UP;
  1768. // compute u,v interpolants
  1769. if ((dx = (xend - xstart))>0)
  1770. {
  1771. du = (ur - ul)/dx;
  1772. dv = (vr - vl)/dx;
  1773. } // end if
  1774. else
  1775. {
  1776. du = (ur - ul);
  1777. dv = (vr - vl);
  1778. } // end else
  1779. // draw span
  1780. for (xi=xstart; xi<=xend; xi++)
  1781. {
  1782. // write textel
  1783.             // get textel
  1784.             textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  1785.             // modulate with base color via light table and write textel
  1786.             screen_ptr[xi] = lightrow444_8[textel];
  1787. // interpolate u,v
  1788. ui+=du;
  1789. vi+=dv;
  1790. } // end for xi
  1791. // interpolate u,v,x along right and left edge
  1792. xl+=dxdyl;
  1793. ul+=dudyl;
  1794. vl+=dvdyl;
  1795. xr+=dxdyr;
  1796. ur+=dudyr;
  1797. vr+=dvdyr;
  1798. // advance screen ptr
  1799. screen_ptr+=mem_pitch;
  1800. // test for yi hitting second region, if so change interpolant
  1801. if (yi==yrestart)
  1802. {
  1803. // test interpolation side change flag
  1804. if (irestart == INTERP_LHS)
  1805. {
  1806. // LHS
  1807. dyl = (y2 - y1);
  1808. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  1809. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  1810. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  1811. // set starting values
  1812. xl = (x1  << FIXP16_SHIFT);
  1813. ul = (tu1 << FIXP16_SHIFT);
  1814. vl = (tv1 << FIXP16_SHIFT);
  1815. // interpolate down on LHS to even up
  1816. xl+=dxdyl;
  1817. ul+=dudyl;
  1818. vl+=dvdyl;
  1819. } // end if
  1820. else
  1821. {
  1822. // RHS
  1823. dyr = (y1 - y2);
  1824. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  1825. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  1826. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  1827. // set starting values
  1828. xr = (x2  << FIXP16_SHIFT);
  1829. ur = (tu2 << FIXP16_SHIFT);
  1830. vr = (tv2 << FIXP16_SHIFT);
  1831. // interpolate down on RHS to even up
  1832. xr+=dxdyr;
  1833. ur+=dudyr;
  1834. vr+=dvdyr;
  1835. } // end else
  1836. } // end if
  1837. } // end for y
  1838. } // end else
  1839. } // end if
  1840. } // end Draw_Textured_TriangleFS
  1841. /////////////////////////////////////////////////////////////
  1842. void Draw_Textured_Triangle16(POLYF4DV2_PTR face,   // ptr to face
  1843.                               UCHAR *_dest_buffer,   // pointer to video buffer
  1844.                               int mem_pitch)        // bytes per line, 320, 640 etc.
  1845. {
  1846. // this function draws a textured triangle in 16-bit mode
  1847. int v0=0,
  1848.     v1=1,
  1849. v2=2,
  1850. temp=0,
  1851. tri_type = TRI_TYPE_NONE,
  1852. irestart = INTERP_LHS;
  1853. int dx,dy,dyl,dyr,      // general deltas
  1854.     u,v,
  1855.     du,dv,
  1856.     xi,yi,              // the current interpolated x,y
  1857. ui,vi,              // the current interpolated u,v
  1858. index_x,index_y,    // looping vars
  1859. x,y,                // hold general x,y
  1860. xstart,
  1861. xend,
  1862. ystart,
  1863. yrestart,
  1864. yend,
  1865. xl,                 
  1866. dxdyl,              
  1867. xr,
  1868. dxdyr,             
  1869. dudyl,    
  1870. ul,
  1871. dvdyl,   
  1872. vl,
  1873. dudyr,
  1874. ur,
  1875. dvdyr,
  1876. vr;
  1877. int x0,y0,tu0,tv0,    // cached vertices
  1878. x1,y1,tu1,tv1,
  1879. x2,y2,tu2,tv2;
  1880. USHORT *screen_ptr  = NULL,
  1881.    *screen_line = NULL,
  1882.    *textmap     = NULL,
  1883.        *dest_buffer = (USHORT *)_dest_buffer;
  1884. #ifdef DEBUG_ON
  1885. // track rendering stats
  1886.     debug_polys_rendered_per_frame++;
  1887. #endif
  1888. // extract texture map
  1889. textmap = (USHORT *)face->texture->buffer;
  1890. // extract base 2 of texture width
  1891. int texture_shift2 = logbase2ofx[face->texture->width];
  1892. // adjust memory pitch to words, divide by 2
  1893. mem_pitch >>=1;
  1894. // first trivial clipping rejection tests 
  1895. if (((face->tvlist[0].y < min_clip_y)  && 
  1896.  (face->tvlist[1].y < min_clip_y)  &&
  1897.  (face->tvlist[2].y < min_clip_y)) ||
  1898. ((face->tvlist[0].y > max_clip_y)  && 
  1899.  (face->tvlist[1].y > max_clip_y)  &&
  1900.  (face->tvlist[2].y > max_clip_y)) ||
  1901. ((face->tvlist[0].x < min_clip_x)  && 
  1902.  (face->tvlist[1].x < min_clip_x)  &&
  1903.  (face->tvlist[2].x < min_clip_x)) ||
  1904. ((face->tvlist[0].x > max_clip_x)  && 
  1905.  (face->tvlist[1].x > max_clip_x)  &&
  1906.  (face->tvlist[2].x > max_clip_x)))
  1907.    return;
  1908. // degenerate triangle
  1909. if ( ((face->tvlist[0].x==face->tvlist[1].x) && (face->tvlist[1].x==face->tvlist[2].x)) ||
  1910.  ((face->tvlist[0].y==face->tvlist[1].y) && (face->tvlist[1].y==face->tvlist[2].y)))
  1911.    return;
  1912. // sort vertices
  1913. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  1914. {SWAP(v0,v1,temp);} 
  1915. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  1916. {SWAP(v0,v2,temp);}
  1917. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  1918. {SWAP(v1,v2,temp);}
  1919. // now test for trivial flat sided cases
  1920. if (face->tvlist[v0].y==face->tvlist[v1].y)
  1921. // set triangle type
  1922. tri_type = TRI_TYPE_FLAT_TOP;
  1923. // sort vertices left to right
  1924. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  1925. {SWAP(v0,v1,temp);}
  1926. } // end if
  1927. else
  1928. // now test for trivial flat sided cases
  1929. if (face->tvlist[v1].y==face->tvlist[v2].y)
  1930. // set triangle type
  1931. tri_type = TRI_TYPE_FLAT_BOTTOM;
  1932. // sort vertices left to right
  1933. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  1934. {SWAP(v1,v2,temp);}
  1935. } // end if
  1936. else
  1937. {
  1938. // must be a general triangle
  1939. tri_type = TRI_TYPE_GENERAL;
  1940. } // end else
  1941. // extract vertices for processing, now that we have order
  1942. x0  = (int)(face->tvlist[v0].x+0.5);
  1943. y0  = (int)(face->tvlist[v0].y+0.5);
  1944. tu0 = (int)(face->tvlist[v0].u0);
  1945. tv0 = (int)(face->tvlist[v0].v0);
  1946. x1  = (int)(face->tvlist[v1].x+0.5);
  1947. y1  = (int)(face->tvlist[v1].y+0.5);
  1948. tu1 = (int)(face->tvlist[v1].u0);
  1949. tv1 = (int)(face->tvlist[v1].v0);
  1950. x2  = (int)(face->tvlist[v2].x+0.5);
  1951. y2  = (int)(face->tvlist[v2].y+0.5);
  1952. tu2 = (int)(face->tvlist[v2].u0);
  1953. tv2 = (int)(face->tvlist[v2].v0);
  1954. // set interpolation restart value
  1955. yrestart = y1;
  1956. // what kind of triangle
  1957. if (tri_type & TRI_TYPE_FLAT_MASK)
  1958. {
  1959. if (tri_type == TRI_TYPE_FLAT_TOP)
  1960. {
  1961. // compute all deltas
  1962. dy = (y2 - y0);
  1963. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  1964. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  1965. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  1966. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  1967. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  1968. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  1969. // test for y clipping
  1970. if (y0 < min_clip_y)
  1971. {
  1972. // compute overclip
  1973. dy = (min_clip_y - y0);
  1974. // computer new LHS starting values
  1975. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  1976. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  1977. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  1978. // compute new RHS starting values
  1979. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  1980. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  1981. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  1982. // compute new starting y
  1983. ystart = min_clip_y;
  1984. } // end if
  1985. else
  1986. {
  1987. // no clipping
  1988. // set starting values
  1989. xl = (x0 << FIXP16_SHIFT);
  1990. xr = (x1 << FIXP16_SHIFT);
  1991. ul = (tu0 << FIXP16_SHIFT);
  1992. vl = (tv0 << FIXP16_SHIFT);
  1993. ur = (tu1 << FIXP16_SHIFT);
  1994. vr = (tv1 << FIXP16_SHIFT);
  1995. // set starting y
  1996. ystart = y0;
  1997. } // end else
  1998. } // end if flat top
  1999. else
  2000. {
  2001. // must be flat bottom
  2002. // compute all deltas
  2003. dy = (y1 - y0);
  2004. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  2005. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  2006. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  2007. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2008. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2009. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  2010. // test for y clipping
  2011. if (y0 < min_clip_y)
  2012. {
  2013. // compute overclip
  2014. dy = (min_clip_y - y0);
  2015. // computer new LHS starting values
  2016. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2017. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2018. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2019. // compute new RHS starting values
  2020. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2021. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2022. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2023. // compute new starting y
  2024. ystart = min_clip_y;
  2025. } // end if
  2026. else
  2027. {
  2028. // no clipping
  2029. // set starting values
  2030. xl = (x0 << FIXP16_SHIFT);
  2031. xr = (x0 << FIXP16_SHIFT);
  2032. ul = (tu0 << FIXP16_SHIFT);
  2033. vl = (tv0 << FIXP16_SHIFT);
  2034. ur = (tu0 << FIXP16_SHIFT);
  2035. vr = (tv0 << FIXP16_SHIFT);
  2036. // set starting y
  2037. ystart = y0;
  2038. } // end else
  2039. } // end else flat bottom
  2040. // test for bottom clip, always
  2041. if ((yend = y2) > max_clip_y)
  2042. yend = max_clip_y;
  2043.     // test for horizontal clipping
  2044. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2045. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2046. (x2 < min_clip_x) || (x2 > max_clip_x))
  2047. {
  2048.     // clip version
  2049. // point screen ptr to starting line
  2050. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2051. for (yi = ystart; yi<=yend; yi++)
  2052. {
  2053. // compute span endpoints
  2054. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2055. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2056. // compute starting points for u,v interpolants
  2057. ui = ul + FIXP16_ROUND_UP;
  2058. vi = vl + FIXP16_ROUND_UP;
  2059. // compute u,v interpolants
  2060. if ((dx = (xend - xstart))>0)
  2061. {
  2062. du = (ur - ul)/dx;
  2063. dv = (vr - vl)/dx;
  2064. } // end if
  2065. else
  2066. {
  2067. du = (ur - ul);
  2068. dv = (vr - vl);
  2069. } // end else
  2070. ///////////////////////////////////////////////////////////////////////
  2071. // test for x clipping, LHS
  2072. if (xstart < min_clip_x)
  2073. {
  2074. // compute x overlap
  2075. dx = min_clip_x - xstart;
  2076. // slide interpolants over
  2077. ui+=dx*du;
  2078. vi+=dx*dv;
  2079. // reset vars
  2080. xstart = min_clip_x;
  2081. } // end if
  2082. // test for x clipping RHS
  2083. if (xend > max_clip_x)
  2084. xend = max_clip_x;
  2085. ///////////////////////////////////////////////////////////////////////
  2086. // draw span
  2087. for (xi=xstart; xi<=xend; xi++)
  2088. {
  2089. // write textel
  2090.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2091. // interpolate u,v
  2092. ui+=du;
  2093. vi+=dv;
  2094. } // end for xi
  2095. // interpolate u,v,x along right and left edge
  2096. xl+=dxdyl;
  2097. ul+=dudyl;
  2098. vl+=dvdyl;
  2099. xr+=dxdyr;
  2100. ur+=dudyr;
  2101. vr+=dvdyr;
  2102.  
  2103. // advance screen ptr
  2104. screen_ptr+=mem_pitch;
  2105. } // end for y
  2106. } // end if clip
  2107. else
  2108. {
  2109. // non-clip version
  2110. // point screen ptr to starting line
  2111. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2112. for (yi = ystart; yi<=yend; yi++)
  2113. {
  2114. // compute span endpoints
  2115. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2116. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2117. // compute starting points for u,v interpolants
  2118. ui = ul + FIXP16_ROUND_UP;
  2119. vi = vl + FIXP16_ROUND_UP;
  2120. // compute u,v interpolants
  2121. if ((dx = (xend - xstart))>0)
  2122. {
  2123. du = (ur - ul)/dx;
  2124. dv = (vr - vl)/dx;
  2125. } // end if
  2126. else
  2127. {
  2128. du = (ur - ul);
  2129. dv = (vr - vl);
  2130. } // end else
  2131. // draw span
  2132. for (xi=xstart; xi<=xend; xi++)
  2133. {
  2134. // write textel
  2135.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) +  ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2136. // interpolate u,v
  2137. ui+=du;
  2138. vi+=dv;
  2139. } // end for xi
  2140. // interpolate u,v,x along right and left edge
  2141. xl+=dxdyl;
  2142. ul+=dudyl;
  2143. vl+=dvdyl;
  2144. xr+=dxdyr;
  2145. ur+=dudyr;
  2146. vr+=dvdyr;
  2147. // advance screen ptr
  2148. screen_ptr+=mem_pitch;
  2149. } // end for y
  2150. } // end if non-clipped
  2151. } // end if
  2152. else
  2153. if (tri_type==TRI_TYPE_GENERAL)
  2154. {
  2155. // first test for bottom clip, always
  2156. if ((yend = y2) > max_clip_y)
  2157. yend = max_clip_y;
  2158. // pre-test y clipping status
  2159. if (y1 < min_clip_y)
  2160. {
  2161. // compute all deltas
  2162. // LHS
  2163. dyl = (y2 - y1);
  2164. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  2165. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2166. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  2167. // RHS
  2168. dyr = (y2 - y0);
  2169. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2170. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2171. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2172. // compute overclip
  2173. dyr = (min_clip_y - y0);
  2174. dyl = (min_clip_y - y1);
  2175. // computer new LHS starting values
  2176. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  2177. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  2178. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  2179. // compute new RHS starting values
  2180. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  2181. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  2182. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  2183. // compute new starting y
  2184. ystart = min_clip_y;
  2185. // test if we need swap to keep rendering left to right
  2186. if (dxdyr > dxdyl)
  2187. {
  2188. SWAP(dxdyl,dxdyr,temp);
  2189. SWAP(dudyl,dudyr,temp);
  2190. SWAP(dvdyl,dvdyr,temp);
  2191. SWAP(xl,xr,temp);
  2192. SWAP(ul,ur,temp);
  2193. SWAP(vl,vr,temp);
  2194. SWAP(x1,x2,temp);
  2195. SWAP(y1,y2,temp);
  2196. SWAP(tu1,tu2,temp);
  2197. SWAP(tv1,tv2,temp);
  2198. // set interpolation restart
  2199. irestart = INTERP_RHS;
  2200. } // end if
  2201. } // end if
  2202. else
  2203. if (y0 < min_clip_y)
  2204. {
  2205. // compute all deltas
  2206. // LHS
  2207. dyl = (y1 - y0);
  2208. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2209. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2210. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2211. // RHS
  2212. dyr = (y2 - y0);
  2213. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2214. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2215. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2216. // compute overclip
  2217. dy = (min_clip_y - y0);
  2218. // computer new LHS starting values
  2219. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2220. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2221. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2222. // compute new RHS starting values
  2223. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2224. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2225. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2226. // compute new starting y
  2227. ystart = min_clip_y;
  2228. // test if we need swap to keep rendering left to right
  2229. if (dxdyr < dxdyl)
  2230. {
  2231. SWAP(dxdyl,dxdyr,temp);
  2232. SWAP(dudyl,dudyr,temp);
  2233. SWAP(dvdyl,dvdyr,temp);
  2234. SWAP(xl,xr,temp);
  2235. SWAP(ul,ur,temp);
  2236. SWAP(vl,vr,temp);
  2237. SWAP(x1,x2,temp);
  2238. SWAP(y1,y2,temp);
  2239. SWAP(tu1,tu2,temp);
  2240. SWAP(tv1,tv2,temp);
  2241. // set interpolation restart
  2242. irestart = INTERP_RHS;
  2243. } // end if
  2244. } // end if
  2245. else
  2246. {
  2247. // no initial y clipping
  2248. // compute all deltas
  2249. // LHS
  2250. dyl = (y1 - y0);
  2251. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2252. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2253. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2254. // RHS
  2255. dyr = (y2 - y0);
  2256. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  2257. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2258. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2259. // no clipping y
  2260. // set starting values
  2261. xl = (x0 << FIXP16_SHIFT);
  2262. xr = (x0 << FIXP16_SHIFT);
  2263. ul = (tu0 << FIXP16_SHIFT);
  2264. vl = (tv0 << FIXP16_SHIFT);
  2265. ur = (tu0 << FIXP16_SHIFT);
  2266. vr = (tv0 << FIXP16_SHIFT);
  2267. // set starting y
  2268. ystart = y0;
  2269. // test if we need swap to keep rendering left to right
  2270. if (dxdyr < dxdyl)
  2271. {
  2272. SWAP(dxdyl,dxdyr,temp);
  2273. SWAP(dudyl,dudyr,temp);
  2274. SWAP(dvdyl,dvdyr,temp);
  2275. SWAP(xl,xr,temp);
  2276. SWAP(ul,ur,temp);
  2277. SWAP(vl,vr,temp);
  2278. SWAP(x1,x2,temp);
  2279. SWAP(y1,y2,temp);
  2280. SWAP(tu1,tu2,temp);
  2281. SWAP(tv1,tv2,temp);
  2282. // set interpolation restart
  2283. irestart = INTERP_RHS;
  2284. } // end if
  2285. } // end else
  2286.     // test for horizontal clipping
  2287. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2288. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2289. (x2 < min_clip_x) || (x2 > max_clip_x))
  2290. {
  2291.     // clip version
  2292. // x clipping
  2293. // point screen ptr to starting line
  2294. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2295. for (yi = ystart; yi<=yend; yi++)
  2296. {
  2297. // compute span endpoints
  2298. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2299. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2300. // compute starting points for u,v interpolants
  2301. ui = ul + FIXP16_ROUND_UP;
  2302. vi = vl + FIXP16_ROUND_UP;
  2303. // compute u,v interpolants
  2304. if ((dx = (xend - xstart))>0)
  2305. {
  2306. du = (ur - ul)/dx;
  2307. dv = (vr - vl)/dx;
  2308. } // end if
  2309. else
  2310. {
  2311. du = (ur - ul);
  2312. dv = (vr - vl);
  2313. } // end else
  2314. ///////////////////////////////////////////////////////////////////////
  2315. // test for x clipping, LHS
  2316. if (xstart < min_clip_x)
  2317. {
  2318. // compute x overlap
  2319. dx = min_clip_x - xstart;
  2320. // slide interpolants over
  2321. ui+=dx*du;
  2322. vi+=dx*dv;
  2323. // set x to left clip edge
  2324. xstart = min_clip_x;
  2325. } // end if
  2326. // test for x clipping RHS
  2327. if (xend > max_clip_x)
  2328. xend = max_clip_x;
  2329. ///////////////////////////////////////////////////////////////////////
  2330. // draw span
  2331. for (xi=xstart; xi<=xend; xi++)
  2332. {
  2333. // write textel
  2334.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2335. // interpolate u,v
  2336. ui+=du;
  2337. vi+=dv;
  2338. } // end for xi
  2339. // interpolate u,v,x along right and left edge
  2340. xl+=dxdyl;
  2341. ul+=dudyl;
  2342. vl+=dvdyl;
  2343. xr+=dxdyr;
  2344. ur+=dudyr;
  2345. vr+=dvdyr;
  2346. // advance screen ptr
  2347. screen_ptr+=mem_pitch;
  2348. // test for yi hitting second region, if so change interpolant
  2349. if (yi==yrestart)
  2350. {
  2351. // test interpolation side change flag
  2352. if (irestart == INTERP_LHS)
  2353. {
  2354. // LHS
  2355. dyl = (y2 - y1);
  2356. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2357. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2358. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2359. // set starting values
  2360. xl = (x1  << FIXP16_SHIFT);
  2361. ul = (tu1 << FIXP16_SHIFT);
  2362. vl = (tv1 << FIXP16_SHIFT);
  2363. // interpolate down on LHS to even up
  2364. xl+=dxdyl;
  2365. ul+=dudyl;
  2366. vl+=dvdyl;
  2367. } // end if
  2368. else
  2369. {
  2370. // RHS
  2371. dyr = (y1 - y2);
  2372. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2373. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2374. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2375. // set starting values
  2376. xr = (x2  << FIXP16_SHIFT);
  2377. ur = (tu2 << FIXP16_SHIFT);
  2378. vr = (tv2 << FIXP16_SHIFT);
  2379. // interpolate down on RHS to even up
  2380. xr+=dxdyr;
  2381. ur+=dudyr;
  2382. vr+=dvdyr;
  2383. } // end else
  2384. } // end if
  2385. } // end for y
  2386. } // end if
  2387. else
  2388. {
  2389. // no x clipping
  2390. // point screen ptr to starting line
  2391. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2392. for (yi = ystart; yi<=yend; yi++)
  2393. {
  2394. // compute span endpoints
  2395. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2396. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2397. // compute starting points for u,v interpolants
  2398. ui = ul + FIXP16_ROUND_UP;
  2399. vi = vl + FIXP16_ROUND_UP;
  2400. // compute u,v interpolants
  2401. if ((dx = (xend - xstart))>0)
  2402. {
  2403. du = (ur - ul)/dx;
  2404. dv = (vr - vl)/dx;
  2405. } // end if
  2406. else
  2407. {
  2408. du = (ur - ul);
  2409. dv = (vr - vl);
  2410. } // end else
  2411. // draw span
  2412. for (xi=xstart; xi<=xend; xi++)
  2413. {
  2414. // write textel
  2415.             screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2416. // interpolate u,v
  2417. ui+=du;
  2418. vi+=dv;
  2419. } // end for xi
  2420. // interpolate u,v,x along right and left edge
  2421. xl+=dxdyl;
  2422. ul+=dudyl;
  2423. vl+=dvdyl;
  2424. xr+=dxdyr;
  2425. ur+=dudyr;
  2426. vr+=dvdyr;
  2427. // advance screen ptr
  2428. screen_ptr+=mem_pitch;
  2429. // test for yi hitting second region, if so change interpolant
  2430. if (yi==yrestart)
  2431. {
  2432. // test interpolation side change flag
  2433. if (irestart == INTERP_LHS)
  2434. {
  2435. // LHS
  2436. dyl = (y2 - y1);
  2437. dxdyl = ((x2 - x1)   << FIXP16_SHIFT)/dyl;
  2438. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2439. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;   
  2440. // set starting values
  2441. xl = (x1  << FIXP16_SHIFT);
  2442. ul = (tu1 << FIXP16_SHIFT);
  2443. vl = (tv1 << FIXP16_SHIFT);
  2444. // interpolate down on LHS to even up
  2445. xl+=dxdyl;
  2446. ul+=dudyl;
  2447. vl+=dvdyl;
  2448. } // end if
  2449. else
  2450. {
  2451. // RHS
  2452. dyr = (y1 - y2);
  2453. dxdyr = ((x1 - x2)   << FIXP16_SHIFT)/dyr;
  2454. dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;  
  2455. dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;   
  2456. // set starting values
  2457. xr = (x2  << FIXP16_SHIFT);
  2458. ur = (tu2 << FIXP16_SHIFT);
  2459. vr = (tv2 << FIXP16_SHIFT);
  2460. // interpolate down on RHS to even up
  2461. xr+=dxdyr;
  2462. ur+=dudyr;
  2463. vr+=dvdyr;
  2464. } // end else
  2465. } // end if
  2466. } // end for y
  2467.    } // end else
  2468. } // end if
  2469. } // end Draw_Textured_Triangle16
  2470. ///////////////////////////////////////////////////////////////////////////////
  2471. void Draw_Textured_TriangleFS16(POLYF4DV2_PTR face,   // ptr to face
  2472.                               UCHAR *_dest_buffer,   // pointer to video buffer
  2473.                               int mem_pitch)        // bytes per line, 320, 640 etc.
  2474. {
  2475. // this function draws a textured triangle in 16-bit mode with flat shading
  2476. int v0=0,
  2477.     v1=1,
  2478. v2=2,
  2479. temp=0,
  2480. tri_type = TRI_TYPE_NONE,
  2481. irestart = INTERP_LHS;
  2482. int dx,dy,dyl,dyr,      // general deltas
  2483.     u,v,
  2484.     du,dv,
  2485.     xi,yi,              // the current interpolated x,y
  2486. ui,vi,              // the current interpolated u,v
  2487. index_x,index_y,    // looping vars
  2488. x,y,                // hold general x,y
  2489. xstart,
  2490. xend,
  2491. ystart,
  2492. yrestart,
  2493. yend,
  2494. xl,                 
  2495. dxdyl,              
  2496. xr,
  2497. dxdyr,             
  2498. dudyl,    
  2499. ul,
  2500. dvdyl,   
  2501. vl,
  2502. dudyr,
  2503. ur,
  2504. dvdyr,
  2505. vr;
  2506. USHORT r_base, g_base, b_base,
  2507.        r_textel, g_textel, b_textel, textel;
  2508. int x0,y0,tu0,tv0,    // cached vertices
  2509. x1,y1,tu1,tv1,
  2510. x2,y2,tu2,tv2;
  2511. USHORT *screen_ptr  = NULL,
  2512.    *screen_line = NULL,
  2513.    *textmap     = NULL,
  2514.        *dest_buffer = (USHORT *)_dest_buffer;
  2515. #ifdef DEBUG_ON
  2516. // track rendering stats
  2517.     debug_polys_rendered_per_frame++;
  2518. #endif
  2519. // extract texture map
  2520. textmap = (USHORT *)face->texture->buffer;
  2521. // extract base 2 of texture width
  2522. int texture_shift2 = logbase2ofx[face->texture->width];
  2523. // adjust memory pitch to words, divide by 2
  2524. mem_pitch >>=1;
  2525. // first trivial clipping rejection tests 
  2526. if (((face->tvlist[0].y < min_clip_y)  && 
  2527.  (face->tvlist[1].y < min_clip_y)  &&
  2528.  (face->tvlist[2].y < min_clip_y)) ||
  2529. ((face->tvlist[0].y > max_clip_y)  && 
  2530.  (face->tvlist[1].y > max_clip_y)  &&
  2531.  (face->tvlist[2].y > max_clip_y)) ||
  2532. ((face->tvlist[0].x < min_clip_x)  && 
  2533.  (face->tvlist[1].x < min_clip_x)  &&
  2534.  (face->tvlist[2].x < min_clip_x)) ||
  2535. ((face->tvlist[0].x > max_clip_x)  && 
  2536.  (face->tvlist[1].x > max_clip_x)  &&
  2537.  (face->tvlist[2].x > max_clip_x)))
  2538.    return;
  2539. // degenerate triangle
  2540. if ( ((face->tvlist[0].x==face->tvlist[1].x) && (face->tvlist[1].x==face->tvlist[2].x)) ||
  2541.  ((face->tvlist[0].y==face->tvlist[1].y) && (face->tvlist[1].y==face->tvlist[2].y)))
  2542.    return;
  2543. // sort vertices
  2544. if (face->tvlist[v1].y < face->tvlist[v0].y) 
  2545. {SWAP(v0,v1,temp);} 
  2546. if (face->tvlist[v2].y < face->tvlist[v0].y) 
  2547. {SWAP(v0,v2,temp);}
  2548. if (face->tvlist[v2].y < face->tvlist[v1].y) 
  2549. {SWAP(v1,v2,temp);}
  2550. // now test for trivial flat sided cases
  2551. if (face->tvlist[v0].y==face->tvlist[v1].y)
  2552. // set triangle type
  2553. tri_type = TRI_TYPE_FLAT_TOP;
  2554. // sort vertices left to right
  2555. if (face->tvlist[v1].x < face->tvlist[v0].x) 
  2556. {SWAP(v0,v1,temp);}
  2557. } // end if
  2558. else
  2559. // now test for trivial flat sided cases
  2560. if (face->tvlist[v1].y==face->tvlist[v2].y)
  2561. // set triangle type
  2562. tri_type = TRI_TYPE_FLAT_BOTTOM;
  2563. // sort vertices left to right
  2564. if (face->tvlist[v2].x < face->tvlist[v1].x) 
  2565. {SWAP(v1,v2,temp);}
  2566. } // end if
  2567. else
  2568. {
  2569. // must be a general triangle
  2570. tri_type = TRI_TYPE_GENERAL;
  2571. } // end else
  2572. // extract base color of lit poly, so we can modulate texture a bit
  2573. // for lighting
  2574. _RGB565FROM16BIT(face->lit_color[0], &r_base, &g_base, &b_base);
  2575. // extract vertices for processing, now that we have order
  2576. x0  = (int)(face->tvlist[v0].x+0.5);
  2577. y0  = (int)(face->tvlist[v0].y+0.5);
  2578. tu0 = (int)(face->tvlist[v0].u0);
  2579. tv0 = (int)(face->tvlist[v0].v0);
  2580. x1  = (int)(face->tvlist[v1].x+0.5);
  2581. y1  = (int)(face->tvlist[v1].y+0.5);
  2582. tu1 = (int)(face->tvlist[v1].u0);
  2583. tv1 = (int)(face->tvlist[v1].v0);
  2584. x2  = (int)(face->tvlist[v2].x+0.5);
  2585. y2  = (int)(face->tvlist[v2].y+0.5);
  2586. tu2 = (int)(face->tvlist[v2].u0);
  2587. tv2 = (int)(face->tvlist[v2].v0);
  2588. // set interpolation restart value
  2589. yrestart = y1;
  2590. // what kind of triangle
  2591. if (tri_type & TRI_TYPE_FLAT_MASK)
  2592. {
  2593. if (tri_type == TRI_TYPE_FLAT_TOP)
  2594. {
  2595. // compute all deltas
  2596. dy = (y2 - y0);
  2597. dxdyl = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2598. dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2599. dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;    
  2600. dxdyr = ((x2 - x1)   << FIXP16_SHIFT)/dy;
  2601. dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;  
  2602. dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;   
  2603. // test for y clipping
  2604. if (y0 < min_clip_y)
  2605. {
  2606. // compute overclip
  2607. dy = (min_clip_y - y0);
  2608. // computer new LHS starting values
  2609. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2610. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2611. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2612. // compute new RHS starting values
  2613. xr = dxdyr*dy + (x1  << FIXP16_SHIFT);
  2614. ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
  2615. vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
  2616. // compute new starting y
  2617. ystart = min_clip_y;
  2618. } // end if
  2619. else
  2620. {
  2621. // no clipping
  2622. // set starting values
  2623. xl = (x0 << FIXP16_SHIFT);
  2624. xr = (x1 << FIXP16_SHIFT);
  2625. ul = (tu0 << FIXP16_SHIFT);
  2626. vl = (tv0 << FIXP16_SHIFT);
  2627. ur = (tu1 << FIXP16_SHIFT);
  2628. vr = (tv1 << FIXP16_SHIFT);
  2629. // set starting y
  2630. ystart = y0;
  2631. } // end else
  2632. } // end if flat top
  2633. else
  2634. {
  2635. // must be flat bottom
  2636. // compute all deltas
  2637. dy = (y1 - y0);
  2638. dxdyl = ((x1 - x0)   << FIXP16_SHIFT)/dy;
  2639. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;  
  2640. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;    
  2641. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dy;
  2642. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;  
  2643. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;   
  2644. // test for y clipping
  2645. if (y0 < min_clip_y)
  2646. {
  2647. // compute overclip
  2648. dy = (min_clip_y - y0);
  2649. // computer new LHS starting values
  2650. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2651. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2652. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2653. // compute new RHS starting values
  2654. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2655. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2656. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2657. // compute new starting y
  2658. ystart = min_clip_y;
  2659. } // end if
  2660. else
  2661. {
  2662. // no clipping
  2663. // set starting values
  2664. xl = (x0 << FIXP16_SHIFT);
  2665. xr = (x0 << FIXP16_SHIFT);
  2666. ul = (tu0 << FIXP16_SHIFT);
  2667. vl = (tv0 << FIXP16_SHIFT);
  2668. ur = (tu0 << FIXP16_SHIFT);
  2669. vr = (tv0 << FIXP16_SHIFT);
  2670. // set starting y
  2671. ystart = y0;
  2672. } // end else
  2673. } // end else flat bottom
  2674. // test for bottom clip, always
  2675. if ((yend = y2) > max_clip_y)
  2676. yend = max_clip_y;
  2677.     // test for horizontal clipping
  2678. if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
  2679. (x1 < min_clip_x) || (x1 > max_clip_x) ||
  2680. (x2 < min_clip_x) || (x2 > max_clip_x))
  2681. {
  2682.     // clip version
  2683. // point screen ptr to starting line
  2684. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2685. for (yi = ystart; yi<=yend; yi++)
  2686. {
  2687. // compute span endpoints
  2688. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2689. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2690. // compute starting points for u,v interpolants
  2691. ui = ul + FIXP16_ROUND_UP;
  2692. vi = vl + FIXP16_ROUND_UP;
  2693. // compute u,v interpolants
  2694. if ((dx = (xend - xstart))>0)
  2695. {
  2696. du = (ur - ul)/dx;
  2697. dv = (vr - vl)/dx;
  2698. } // end if
  2699. else
  2700. {
  2701. du = (ur - ul);
  2702. dv = (vr - vl);
  2703. } // end else
  2704. ///////////////////////////////////////////////////////////////////////
  2705. // test for x clipping, LHS
  2706. if (xstart < min_clip_x)
  2707. {
  2708. // compute x overlap
  2709. dx = min_clip_x - xstart;
  2710. // slide interpolants over
  2711. ui+=dx*du;
  2712. vi+=dx*dv;
  2713. // reset vars
  2714. xstart = min_clip_x;
  2715. } // end if
  2716. // test for x clipping RHS
  2717. if (xend > max_clip_x)
  2718. xend = max_clip_x;
  2719. ///////////////////////////////////////////////////////////////////////
  2720. // draw span
  2721. for (xi=xstart; xi<=xend; xi++)
  2722. {
  2723. // write textel
  2724.     // get textel first
  2725.   textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  2726.             // extract rgb components
  2727.             r_textel  = ((textel >> 11)       ); 
  2728.             g_textel  = ((textel >> 5)  & 0x3f); 
  2729.             b_textel =   (textel        & 0x1f);
  2730.             // modulate textel with lit background color
  2731.             r_textel*=r_base; 
  2732.             g_textel*=g_base;
  2733.             b_textel*=b_base;
  2734.             // finally write pixel, note that we did the math such that the results are r*32, g*64, b*32
  2735.             // hence we need to divide the results by 32,64,32 respetively, BUT since we need to shift
  2736.             // the results to fit into the destination 5.6.5 word, we can take advantage of the shifts
  2737.             // and they all cancel out for the most part, but we will need logical anding, we will do
  2738.             // it later when we optimize more...
  2739.             screen_ptr[xi] = ((b_textel >> 5) + ((g_textel >> 6) << 5) + ((r_textel >> 5) << 11));
  2740. // interpolate u,v
  2741. ui+=du;
  2742. vi+=dv;
  2743. } // end for xi
  2744. // interpolate u,v,x along right and left edge
  2745. xl+=dxdyl;
  2746. ul+=dudyl;
  2747. vl+=dvdyl;
  2748. xr+=dxdyr;
  2749. ur+=dudyr;
  2750. vr+=dvdyr;
  2751.  
  2752. // advance screen ptr
  2753. screen_ptr+=mem_pitch;
  2754. } // end for y
  2755. } // end if clip
  2756. else
  2757. {
  2758. // non-clip version
  2759. // point screen ptr to starting line
  2760. screen_ptr = dest_buffer + (ystart * mem_pitch);
  2761. for (yi = ystart; yi<=yend; yi++)
  2762. {
  2763. // compute span endpoints
  2764. xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2765. xend   = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
  2766. // compute starting points for u,v interpolants
  2767. ui = ul + FIXP16_ROUND_UP;
  2768. vi = vl + FIXP16_ROUND_UP;
  2769. // compute u,v interpolants
  2770. if ((dx = (xend - xstart))>0)
  2771. {
  2772. du = (ur - ul)/dx;
  2773. dv = (vr - vl)/dx;
  2774. } // end if
  2775. else
  2776. {
  2777. du = (ur - ul);
  2778. dv = (vr - vl);
  2779. } // end else
  2780. // draw span
  2781. for (xi=xstart; xi<=xend; xi++)
  2782. {
  2783. // write textel
  2784.     // get textel first
  2785.   textel = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
  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. // interpolate u,v
  2801. ui+=du;
  2802. vi+=dv;
  2803. } // end for xi
  2804. // interpolate u,v,x along right and left edge
  2805. xl+=dxdyl;
  2806. ul+=dudyl;
  2807. vl+=dvdyl;
  2808. xr+=dxdyr;
  2809. ur+=dudyr;
  2810. vr+=dvdyr;
  2811. // advance screen ptr
  2812. screen_ptr+=mem_pitch;
  2813. } // end for y
  2814. } // end if non-clipped
  2815. } // end if
  2816. else
  2817. if (tri_type==TRI_TYPE_GENERAL)
  2818. {
  2819. // first test for bottom clip, always
  2820. if ((yend = y2) > max_clip_y)
  2821. yend = max_clip_y;
  2822. // pre-test y clipping status
  2823. if (y1 < min_clip_y)
  2824. {
  2825. // compute all deltas
  2826. // LHS
  2827. dyl = (y2 - y1);
  2828. dxdyl = ((x2  - x1)  << FIXP16_SHIFT)/dyl;
  2829. dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;  
  2830. dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;    
  2831. // RHS
  2832. dyr = (y2 - y0);
  2833. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2834. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2835. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2836. // compute overclip
  2837. dyr = (min_clip_y - y0);
  2838. dyl = (min_clip_y - y1);
  2839. // computer new LHS starting values
  2840. xl = dxdyl*dyl + (x1  << FIXP16_SHIFT);
  2841. ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
  2842. vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
  2843. // compute new RHS starting values
  2844. xr = dxdyr*dyr + (x0  << FIXP16_SHIFT);
  2845. ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
  2846. vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
  2847. // compute new starting y
  2848. ystart = min_clip_y;
  2849. // test if we need swap to keep rendering left to right
  2850. if (dxdyr > dxdyl)
  2851. {
  2852. SWAP(dxdyl,dxdyr,temp);
  2853. SWAP(dudyl,dudyr,temp);
  2854. SWAP(dvdyl,dvdyr,temp);
  2855. SWAP(xl,xr,temp);
  2856. SWAP(ul,ur,temp);
  2857. SWAP(vl,vr,temp);
  2858. SWAP(x1,x2,temp);
  2859. SWAP(y1,y2,temp);
  2860. SWAP(tu1,tu2,temp);
  2861. SWAP(tv1,tv2,temp);
  2862. // set interpolation restart
  2863. irestart = INTERP_RHS;
  2864. } // end if
  2865. } // end if
  2866. else
  2867. if (y0 < min_clip_y)
  2868. {
  2869. // compute all deltas
  2870. // LHS
  2871. dyl = (y1 - y0);
  2872. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2873. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2874. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2875. // RHS
  2876. dyr = (y2 - y0);
  2877. dxdyr = ((x2  - x0)  << FIXP16_SHIFT)/dyr;
  2878. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2879. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2880. // compute overclip
  2881. dy = (min_clip_y - y0);
  2882. // computer new LHS starting values
  2883. xl = dxdyl*dy + (x0  << FIXP16_SHIFT);
  2884. ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
  2885. vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
  2886. // compute new RHS starting values
  2887. xr = dxdyr*dy + (x0  << FIXP16_SHIFT);
  2888. ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
  2889. vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
  2890. // compute new starting y
  2891. ystart = min_clip_y;
  2892. // test if we need swap to keep rendering left to right
  2893. if (dxdyr < dxdyl)
  2894. {
  2895. SWAP(dxdyl,dxdyr,temp);
  2896. SWAP(dudyl,dudyr,temp);
  2897. SWAP(dvdyl,dvdyr,temp);
  2898. SWAP(xl,xr,temp);
  2899. SWAP(ul,ur,temp);
  2900. SWAP(vl,vr,temp);
  2901. SWAP(x1,x2,temp);
  2902. SWAP(y1,y2,temp);
  2903. SWAP(tu1,tu2,temp);
  2904. SWAP(tv1,tv2,temp);
  2905. // set interpolation restart
  2906. irestart = INTERP_RHS;
  2907. } // end if
  2908. } // end if
  2909. else
  2910. {
  2911. // no initial y clipping
  2912. // compute all deltas
  2913. // LHS
  2914. dyl = (y1 - y0);
  2915. dxdyl = ((x1  - x0)  << FIXP16_SHIFT)/dyl;
  2916. dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;  
  2917. dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;    
  2918. // RHS
  2919. dyr = (y2 - y0);
  2920. dxdyr = ((x2 - x0)   << FIXP16_SHIFT)/dyr;
  2921. dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;  
  2922. dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;   
  2923. // no clipping y
  2924. // set starting values
  2925. xl = (x0 << FIXP16_SHIFT);
  2926. xr = (x0 << FIXP16_SHIFT);
  2927. ul = (tu0 << FIXP16_SHIFT);
  2928. vl = (tv0 << FIXP16_SHIFT);
  2929. ur = (tu0 << FIXP16_SHIFT);
  2930. vr = (tv0 << FIXP16_SHIFT);