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

游戏

开发平台:

Visual C++

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