t3dlib10.cpp
资源名称:Source.rar [点击查看]
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:1310k
源码类别:
游戏
开发平台:
Visual C++
- // set the shading mode flag in material
- SET_BIT(materials[curr_material + num_materials].attr, MATV1_ATTR_SHADE_MODE_GOURAUD);
- } // end if
- else
- if (strcmp(parser.pstrings[2], "phong") == 0)
- {
- // set the shading mode flag in material
- SET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_SHADE_MODE_FASTPHONG);
- } // end if
- else
- {
- // set the shading mode flag in material
- SET_BIT(materials[material_index + num_materials].attr, MATV1_ATTR_SHADE_MODE_FLAT);
- } // end else
- break;
- } // end if
- } // end while
- // found the material, break out of while for another pass
- break;
- } // end if found material
- } // end while looking for mat#1
- } // end for curr_material
- // before performing texture application we need to determine if the texture on this
- // object is mipmapped, if so we need to create a mip map chain, and set the proper
- // attributes in both the object and the polygons themselves
- if (mipmap==1)
- {
- // set the mipmap bit in the object
- SET_BIT(obj->attr, OBJECT4DV2_ATTR_MIPMAP);
- // now with the base texture as level d=0 call the mipmap chain generator
- Generate_Mipmaps(obj->texture, (BITMAP_IMAGE_PTR *)&obj->texture); // (BITMAP_IMAGE_PTR *)&obj->texture);
- } // end if
- // at this point poly_material[] holds all the indices for the polygon materials (zero based, so they need fix up)
- // and we must access the materials array to fill in each polygon with the polygon color, etc.
- // now that we finally have the material libary loaded
- for (int curr_poly = 0; curr_poly < obj->num_polys; curr_poly++)
- {
- Write_Error("nfixing poly material %d from index %d to index %d", curr_poly,
- poly_material[curr_poly],
- poly_material[curr_poly] + num_materials );
- // fix up offset
- poly_material[curr_poly] = poly_material[curr_poly] + num_materials;
- // we need to know what color depth we are dealing with, so check
- // the bits per pixel, this assumes that the system has already
- // made the call to DDraw_Init() or set the bit depth
- if (screen_bpp == 16)
- {
- // cool, 16 bit mode
- SET_BIT(obj->plist[curr_poly].attr,POLY4DV1_ATTR_RGB16);
- // test if this is a textured poly, if so override the color to WHITE,
- // so we get maximum reflection in lighting stage
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_TEXTURE)
- obj->plist[curr_poly].color = RGB16Bit(255,255,255);
- else
- obj->plist[curr_poly].color = RGB16Bit(materials[ poly_material[curr_poly] ].color.r,
- materials[ poly_material[curr_poly] ].color.g,
- materials[ poly_material[curr_poly] ].color.b);
- Write_Error("nPolygon 16-bit");
- } // end
- else
- {
- // 8 bit mode
- SET_BIT(obj->plist[curr_poly].attr,POLY4DV1_ATTR_8BITCOLOR);
- // test if this is a textured poly, if so override the color to WHITE,
- // so we get maximum reflection in lighting stage
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_TEXTURE)
- obj->plist[curr_poly].color = RGBto8BitIndex(255, 255, 255, palette, 0);
- else
- obj->plist[curr_poly].color = RGBto8BitIndex(materials[ poly_material[curr_poly] ].color.r,
- materials[ poly_material[curr_poly] ].color.g,
- materials[ poly_material[curr_poly] ].color.b,
- palette, 0);
- Write_Error("nPolygon 8-bit, index=%d", obj->plist[curr_poly].color);
- } // end else
- // now set all the shading flags
- // figure out which shader to use
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_CONSTANT)
- {
- // set shading mode
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_SHADE_MODE_CONSTANT);
- } // end if
- else
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_FLAT)
- {
- // set shading mode
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_SHADE_MODE_FLAT);
- } // end if
- else
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_GOURAUD)
- {
- // set shading mode
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_SHADE_MODE_GOURAUD);
- // going to need vertex normals!
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[0] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[1] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[2] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- } // end if
- else
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_FASTPHONG)
- {
- // set shading mode
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_SHADE_MODE_FASTPHONG);
- // going to need vertex normals!
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[0] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[1] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[2] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- } // end if
- else
- {
- // set shading mode to default flat
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_SHADE_MODE_FLAT);
- } // end if
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_SHADE_MODE_TEXTURE)
- {
- // set shading mode
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_SHADE_MODE_TEXTURE);
- // apply texture to this polygon
- obj->plist[curr_poly].texture = obj->texture;
- // if the object was mipmapped this above assignment will just point the texture to
- // the mipmap chain array, however we still need to set the polygon attribute, so
- // we know the poly is mip mapped, since once its in the rendering list we will have
- // no idea
- if (mipmap)
- SET_BIT(obj->plist[curr_poly].attr,POLY4DV2_ATTR_MIPMAP);
- // set texture coordinate attributes
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[0] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[1] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[curr_poly].vert[2] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- } // end if
- // now test for alpha channel
- if (materials[ poly_material[curr_poly] ].attr & MATV1_ATTR_TRANSPARENT)
- {
- // set the value of the alpha channel, upper 8-bits of color will be used to hold it
- // lets hope this doesn't break the lighting engine!!!!
- obj->plist[curr_poly].color+= (materials[ poly_material[curr_poly] ].color.a << 24);
- // set the alpha flag in polygon
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_TRANSPARENT);
- } // end if
- // set the material mode to ver. 1.0 emulation (for now only!!!)
- SET_BIT(obj->plist[curr_poly].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
- } // end for curr_poly
- // local object materials have been added to database, update total materials in system
- num_materials+=num_materials_object;
- // now fix up all texture coordinates
- if (obj->texture)
- {
- for (tvertex = 0; tvertex < num_texture_vertices; tvertex++)
- {
- // step 1: scale the texture coordinates by the texture size in lod = 0
- // make sure to access mipmap chain if needed!!!!!!!
- int texture_size;
- if (!mipmap)
- texture_size = obj->texture->width;
- else // must be a mipmap chain, cast pointer to ptr to array of pointers and access elem 0
- texture_size = ((BITMAP_IMAGE_PTR *)(obj->texture))[0]->width;
- // scale 0..1 to 0..texture_size-1
- obj->tlist[tvertex].x *= (texture_size-1);
- obj->tlist[tvertex].y *= (texture_size-1);
- // now test for vertex transformation flags
- if (vertex_flags & VERTEX_FLAGS_INVERT_TEXTURE_U)
- {
- obj->tlist[tvertex].x = (texture_size-1) - obj->tlist[tvertex].x;
- } // end if
- if (vertex_flags & VERTEX_FLAGS_INVERT_TEXTURE_V)
- {
- obj->tlist[tvertex].y = (texture_size-1) - obj->tlist[tvertex].y;
- } // end if
- if (vertex_flags & VERTEX_FLAGS_INVERT_SWAP_UV)
- {
- float temp;
- SWAP(obj->tlist[tvertex].x, obj->tlist[tvertex].y, temp);
- } // end if
- } // end for
- } // end if there was a texture loaded for this object
- #ifdef DEBUG_ON
- for (curr_material = 0; curr_material < num_materials; curr_material++)
- {
- Write_Error("nMaterial %d", curr_material);
- Write_Error("nint state = %d", materials[curr_material].state);
- Write_Error("nint id = %d", materials[curr_material].id);
- Write_Error("nchar name[64] = %s", materials[curr_material].name);
- Write_Error("nint attr = %d", materials[curr_material].attr);
- Write_Error("nint r = %d", materials[curr_material].color.r);
- Write_Error("nint g = %d", materials[curr_material].color.g);
- Write_Error("nint b = %d", materials[curr_material].color.b);
- Write_Error("nint alpha = %d", materials[curr_material].color.a);
- Write_Error("nint color = %d", materials[curr_material].attr);
- Write_Error("nfloat ka = %f", materials[curr_material].ka);
- Write_Error("nkd = %f", materials[curr_material].kd);
- Write_Error("nks = %f", materials[curr_material].ks);
- Write_Error("npower = %f", materials[curr_material].power);
- Write_Error("nchar texture_file = %sn", materials[curr_material].texture_file);
- } // end for curr_material
- #endif
- // now that we know the correct number of polygons, we must allocate memory for them
- // and fix up the object, this is a hack, but the file formats are so stupid by not
- // all starting with NUM_VERTICES, NUM_POLYGONS -- that would make everyone's life
- // easier!
- #if 0
- // step 1: allocate memory for the polygons
- POLY4DV2_PTR plist_temp = NULL;
- // allocate memory for polygon list, the correct number of polys was overwritten
- // into the object during parsing, so we can use the num_polys field
- if (!(plist_temp = (POLY4DV2_PTR)malloc(sizeof(POLY4DV2)*obj->num_polys)))
- return(0);
- // step 2: now copy the polygons into the correct list
- memcpy((void *)plist_temp, (void *)obj->plist, sizeof(POLY4DV2));
- // step 3: now free the old memory and fix the pointer
- free(obj->plist);
- // now fix the pointer
- obj->plist = plist_temp;
- #endif
- // compute the polygon normal lengths
- Compute_OBJECT4DV2_Poly_Normals(obj);
- // compute vertex normals for any gouraud shaded polys
- Compute_OBJECT4DV2_Vertex_Normals(obj);
- // return success
- return(1);
- } // end Load_OBJECT4DV2_COB2
- ////////////////////////////////////////////////////////////////////////////////////////
- int Generate_Terrain2_OBJECT4DV2(OBJECT4DV2_PTR obj, // pointer to object
- float twidth, // width in world coords on x-axis
- float theight, // height (length) in world coords on z-axis
- float vscale, // vertical scale of terrain
- char *height_map_file, // filename of height bitmap encoded in 256 colors
- char *texture_map_file, // filename of texture map
- int rgbcolor, // color of terrain if no texture
- VECTOR4D_PTR pos, // initial position
- VECTOR4D_PTR rot, // initial rotations
- int poly_attr, // the shading attributes we would like
- float sea_level, // height of sea level
- int alpha) // alpha level to make all polys below sea level
- {
- // this function generates a terrain of width x height in the x-z plane
- // the terrain is defined by a height field encoded as color values
- // of a 256 color texture, 0 being ground level 255 being 1.0, this value
- // is scaled by vscale for the height of each point in the height field
- // the height field generated will be composed of triangles where each vertex
- // in the height field is derived from the height map, thus if the height map
- // is 256 x 256 points then the final mesh will be (256-1) x (256-1) polygons
- // with a absolute world size of width x height (in the x-z plane)
- // also if there is a texture map file then it will be mapped onto the terrain
- // and texture coordinates will be generated
- // this version allows transparency control for "sea level", if transparency is
- // desired to create transparent water, send a non negative for alpha
- // alpha must be between 0 and 255, 255.0 being fully opaque
- char buffer[256]; // working buffer
- float col_tstep, row_tstep;
- float col_vstep, row_vstep;
- int columns, rows;
- int rgbwhite;
- BITMAP_FILE height_bitmap; // holds the height bitmap
- // Step 1: clear out the object and initialize it a bit
- memset(obj, 0, sizeof(OBJECT4DV2));
- // set state of object to active and visible
- obj->state = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;
- // set position of object
- obj->world_pos.x = pos->x;
- obj->world_pos.y = pos->y;
- obj->world_pos.z = pos->z;
- obj->world_pos.w = pos->w;
- // create proper color word based on selected bit depth of terrain
- // rgbcolor is always in rgb5.6.5 format, so only need to downconvert for
- // 8-bit mesh
- if (poly_attr & POLY4DV1_ATTR_8BITCOLOR)
- {
- rgbcolor = rgblookup[rgbcolor];
- rgbwhite = rgblookup[RGB16Bit(255,255,255)];
- } // end if
- else
- {
- rgbwhite = RGB16Bit(255,255,255);
- } // end else
- // set number of frames
- obj->num_frames = 1;
- obj->curr_frame = 0;
- obj->attr = OBJECT4DV2_ATTR_SINGLE_FRAME;
- // clear the bitmaps out
- memset(&height_bitmap, 0, sizeof(BITMAP_FILE));
- memset(&bitmap16bit, 0, sizeof(BITMAP_FILE));
- // Step 2: load in the height field
- Load_Bitmap_File(&height_bitmap, height_map_file);
- // compute basic information
- columns = height_bitmap.bitmapinfoheader.biWidth;
- rows = height_bitmap.bitmapinfoheader.biHeight;
- col_vstep = twidth / (float)(columns - 1);
- row_vstep = theight / (float)(rows - 1);
- sprintf(obj->name ,"Terrain:%s%s", height_map_file, texture_map_file);
- obj->num_vertices = columns * rows;
- obj->num_polys = ((columns - 1) * (rows - 1) ) * 2;
- // store some results to help with terrain following
- // use the auxialiary variables in the object -- might as well!
- obj->ivar1 = columns;
- obj->ivar2 = rows;
- obj->fvar1 = col_vstep;
- obj->fvar2 = row_vstep;
- // allocate the memory for the vertices and number of polys
- // the call parameters are redundant in this case, but who cares
- if (!Init_OBJECT4DV2(obj, // object to allocate
- obj->num_vertices,
- obj->num_polys,
- obj->num_frames))
- {
- Write_Error("nTerrain generator error (can't allocate memory).");
- } // end if
- // load texture map if there is one
- if ( (poly_attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE) && texture_map_file)
- {
- // load the texture from disk
- Load_Bitmap_File(&bitmap16bit, texture_map_file);
- // create a proper size and bitdepth bitmap
- obj->texture = (BITMAP_IMAGE_PTR)malloc(sizeof(BITMAP_IMAGE));
- Create_Bitmap(obj->texture,0,0,
- bitmap16bit.bitmapinfoheader.biWidth,
- bitmap16bit.bitmapinfoheader.biHeight,
- bitmap16bit.bitmapinfoheader.biBitCount);
- // load the bitmap image (later make this 8/16 bit)
- if (obj->texture->bpp == 16)
- Load_Image_Bitmap16(obj->texture, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
- else
- {
- Load_Image_Bitmap(obj->texture, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
- } // end else 8 bit
- // compute stepping factors in texture map for texture coordinate computation
- col_tstep = (float)(bitmap16bit.bitmapinfoheader.biWidth-1)/(float)(columns - 1);
- row_tstep = (float)(bitmap16bit.bitmapinfoheader.biHeight-1)/(float)(rows - 1);
- // flag object as having textures
- SET_BIT(obj->attr, OBJECT4DV2_ATTR_TEXTURES);
- // done, so unload the bitmap
- Unload_Bitmap_File(&bitmap16bit);
- } // end if
- Write_Error("ncolumns = %d, rows = %d", columns, rows);
- Write_Error("ncol_vstep = %f, row_vstep = %f", col_vstep, row_vstep);
- Write_Error("ncol_tstep=%f, row_tstep=%f", col_tstep, row_tstep);
- Write_Error("nnum_vertices = %d, num_polys = %d", obj->num_vertices, obj->num_polys);
- // Step 4: generate the vertex list, and texture coordinate list in row major form
- for (int curr_row = 0; curr_row < rows; curr_row++)
- {
- for (int curr_col = 0; curr_col < columns; curr_col++)
- {
- int vertex = (curr_row * columns) + curr_col;
- // compute the vertex
- obj->vlist_local[vertex].x = curr_col * col_vstep - (twidth/2);
- obj->vlist_local[vertex].y = vscale*((float)height_bitmap.buffer[curr_col + (curr_row * columns) ]) / 255;
- obj->vlist_local[vertex].z = curr_row * row_vstep - (theight/2);
- obj->vlist_local[vertex].w = 1;
- // every vertex has a point at least, set that in the flags attribute
- SET_BIT(obj->vlist_local[vertex].attr, VERTEX4DTV1_ATTR_POINT);
- // need texture coord?
- if ( (poly_attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE) && texture_map_file)
- {
- // now texture coordinates
- obj->tlist[vertex].x = curr_col * col_tstep;
- obj->tlist[vertex].y = curr_row * row_tstep;
- } // end if
- Write_Error("nVertex %d: V[%f, %f, %f], T[%f, %f]", vertex, obj->vlist_local[vertex].x,
- obj->vlist_local[vertex].y,
- obj->vlist_local[vertex].z,
- obj->tlist[vertex].x,
- obj->tlist[vertex].y);
- } // end for curr_col
- } // end curr_row
- // perform rotation transformation?
- // compute average and max radius
- Compute_OBJECT4DV2_Radius(obj);
- Write_Error("nObject average radius = %f, max radius = %f",
- obj->avg_radius[0], obj->max_radius[0]);
- // Step 5: generate the polygon list
- for (int poly=0; poly < obj->num_polys/2; poly++)
- {
- // polygons follow a regular pattern of 2 per square, row
- // major form, finding the correct indices is a pain, but
- // the bottom line is we have an array of vertices mxn and we need
- // a list of polygons that is (m-1) x (n-1), with 2 triangles per
- // square with a consistent winding order... this is one one to arrive
- // at the indices, another way would be to use two loops, etc.,
- int base_poly_index = (poly % (columns-1)) + (columns * (poly / (columns - 1)) );
- // upper left poly
- obj->plist[poly*2].vert[0] = base_poly_index;
- obj->plist[poly*2].vert[1] = base_poly_index+columns;
- obj->plist[poly*2].vert[2] = base_poly_index+columns+1;
- // lower right poly
- obj->plist[poly*2+1].vert[0] = base_poly_index;
- obj->plist[poly*2+1].vert[1] = base_poly_index+columns+1;
- obj->plist[poly*2+1].vert[2] = base_poly_index+1;
- // point polygon vertex list to object's vertex list
- // note that this is redundant since the polylist is contained
- // within the object in this case and its up to the user to select
- // whether the local or transformed vertex list is used when building up
- // polygon geometry, might be a better idea to set to NULL in the context
- // of polygons that are part of an object
- obj->plist[poly*2].vlist = obj->vlist_local;
- obj->plist[poly*2+1].vlist = obj->vlist_local;
- // set attributes of polygon with sent attributes
- obj->plist[poly*2].attr = poly_attr;
- obj->plist[poly*2+1].attr = poly_attr;
- // now perform some test to make sure any secondary data elements are
- // set properly
- // set color of polygon
- obj->plist[poly*2].color = rgbcolor;
- obj->plist[poly*2+1].color = rgbcolor;
- // check for gouraud of phong shading, if so need normals
- if ( (obj->plist[poly*2].attr & POLY4DV2_ATTR_SHADE_MODE_GOURAUD) ||
- (obj->plist[poly*2].attr & POLY4DV2_ATTR_SHADE_MODE_PHONG) )
- {
- // the vertices from this polygon all need normals, set that in the flags attribute
- SET_BIT(obj->vlist_local[ obj->plist[poly*2].vert[0] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2].vert[1] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2].vert[2] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2+1].vert[0] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2+1].vert[1] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2+1].vert[2] ].attr, VERTEX4DTV1_ATTR_NORMAL);
- } // end if
- // if texture in enabled the enable texture coordinates
- if (poly_attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)
- {
- // apply texture to this polygon
- obj->plist[poly*2].texture = obj->texture;
- obj->plist[poly*2+1].texture = obj->texture;
- // assign the texture coordinates
- // upper left poly
- obj->plist[poly*2].text[0] = base_poly_index;
- obj->plist[poly*2].text[1] = base_poly_index+columns;
- obj->plist[poly*2].text[2] = base_poly_index+columns+1;
- // lower right poly
- obj->plist[poly*2+1].text[0] = base_poly_index;
- obj->plist[poly*2+1].text[1] = base_poly_index+columns+1;
- obj->plist[poly*2+1].text[2] = base_poly_index+1;
- // override base color to make poly more reflective
- obj->plist[poly*2].color = rgbwhite;
- obj->plist[poly*2+1].color = rgbwhite;
- // set texture coordinate attributes
- SET_BIT(obj->vlist_local[ obj->plist[poly*2].vert[0] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2].vert[1] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2].vert[2] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2+1].vert[0] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2+1].vert[1] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- SET_BIT(obj->vlist_local[ obj->plist[poly*2+1].vert[2] ].attr, VERTEX4DTV1_ATTR_TEXTURE);
- } // end if
- // check for alpha enable for sea level polygons to help with water effect
- if (alpha >=0 )
- {
- // compute heights of both polygons
- float avg_y_poly1 = (obj->vlist_local[ obj->plist[poly*2].vert[0] ].y +
- obj->vlist_local[ obj->plist[poly*2].vert[1] ].y +
- obj->vlist_local[ obj->plist[poly*2].vert[2] ].y )/3;
- float avg_y_poly2 = (obj->vlist_local[ obj->plist[poly*2+1].vert[0] ].y +
- obj->vlist_local[ obj->plist[poly*2+1].vert[1] ].y +
- obj->vlist_local[ obj->plist[poly*2+1].vert[2] ].y )/3;
- // test height of poly1 relative to sea level
- if (avg_y_poly1 <= sea_level)
- {
- int ialpha = (int)( (float)alpha/255 * (float)(NUM_ALPHA_LEVELS-1) + (float)0.5);
- // set the alpha color
- obj->plist[poly*2+0].color+= (ialpha << 24);
- // set the alpha flag in polygon
- SET_BIT(obj->plist[poly*2+0].attr, POLY4DV2_ATTR_TRANSPARENT);
- } // end if
- // test height of poly1 relative to sea level
- if (avg_y_poly2 <= sea_level)
- {
- int ialpha = (int)( (float)alpha/255 * (float)(NUM_ALPHA_LEVELS-1) + (float)0.5);
- // set the alpha color
- obj->plist[poly*2+1].color+= (ialpha << 24);
- // set the alpha flag in polygon
- SET_BIT(obj->plist[poly*2+1].attr, POLY4DV2_ATTR_TRANSPARENT);
- } // end if
- } // end if
- // set the material mode to ver. 1.0 emulation
- SET_BIT(obj->plist[poly*2].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
- SET_BIT(obj->plist[poly*2+1].attr, POLY4DV2_ATTR_DISABLE_MATERIAL);
- // finally set the polygon to active
- obj->plist[poly*2].state = POLY4DV2_STATE_ACTIVE;
- obj->plist[poly*2+1].state = POLY4DV2_STATE_ACTIVE;
- // point polygon vertex list to object's vertex list
- // note that this is redundant since the polylist is contained
- // within the object in this case and its up to the user to select
- // whether the local or transformed vertex list is used when building up
- // polygon geometry, might be a better idea to set to NULL in the context
- // of polygons that are part of an object
- obj->plist[poly*2].vlist = obj->vlist_local;
- obj->plist[poly*2+1].vlist = obj->vlist_local;
- // set texture coordinate list, this is needed
- obj->plist[poly*2].tlist = obj->tlist;
- obj->plist[poly*2+1].tlist = obj->tlist;
- } // end for poly
- #if 0
- for (poly=0; poly < obj->num_polys; poly++)
- {
- Write_Error("nPoly %d: Vi[%d, %d, %d], Ti[%d, %d, %d]",poly,
- obj->plist[poly].vert[0],
- obj->plist[poly].vert[1],
- obj->plist[poly].vert[2],
- obj->plist[poly].text[0],
- obj->plist[poly].text[1],
- obj->plist[poly].text[2]);
- } // end
- #endif
- // compute the polygon normal lengths
- Compute_OBJECT4DV2_Poly_Normals(obj);
- // compute vertex normals for any gouraud shaded polys
- Compute_OBJECT4DV2_Vertex_Normals(obj);
- // return success
- return(1);
- } // end Generate_Terrain2_OBJECT4DV2
- ///////////////////////////////////////////////////////////////////////////////
- // 1/z Buffer non alpha functions
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Textured_TriangleINVZB_16(POLYF4DV2_PTR face, // ptr to face
- UCHAR *_dest_buffer, // pointer to video buffer
- int mem_pitch, // bytes per line, 320, 640 etc.
- UCHAR *_zbuffer, // pointer to z-buffer
- int zpitch) // bytes per line of zbuffer
- {
- // this function draws a textured triangle in 16-bit mode
- int v0=0,
- v1=1,
- v2=2,
- temp=0,
- tri_type = TRI_TYPE_NONE,
- irestart = INTERP_LHS;
- int dx,dy,dyl,dyr, // general deltas
- u,v,z,
- du,dv,dz,
- xi,yi, // the current interpolated x,y
- ui,vi,zi, // the current interpolated u,v,z
- index_x,index_y, // looping vars
- x,y, // hold general x,y
- xstart,
- xend,
- ystart,
- yrestart,
- yend,
- xl,
- dxdyl,
- xr,
- dxdyr,
- dudyl,
- ul,
- dvdyl,
- vl,
- dzdyl,
- zl,
- dudyr,
- ur,
- dvdyr,
- vr,
- dzdyr,
- zr;
- int x0,y0,tu0,tv0,tz0, // cached vertices
- x1,y1,tu1,tv1,tz1,
- x2,y2,tu2,tv2,tz2;
- USHORT *screen_ptr = NULL,
- *screen_line = NULL,
- *textmap = NULL,
- *dest_buffer = (USHORT *)_dest_buffer;
- UINT *z_ptr = NULL,
- *zbuffer = (UINT *)_zbuffer;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // extract texture map
- textmap = (USHORT *)face->texture->buffer;
- // extract base 2 of texture width
- int texture_shift2 = logbase2ofx[face->texture->width];
- // adjust memory pitch to words, divide by 2
- mem_pitch >>=1;
- // adjust zbuffer pitch for 32 bit alignment
- zpitch >>= 2;
- // apply fill convention to coordinates
- face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
- // first trivial clipping rejection tests
- if (((face->tvlist[0].y < min_clip_y) &&
- (face->tvlist[1].y < min_clip_y) &&
- (face->tvlist[2].y < min_clip_y)) ||
- ((face->tvlist[0].y > max_clip_y) &&
- (face->tvlist[1].y > max_clip_y) &&
- (face->tvlist[2].y > max_clip_y)) ||
- ((face->tvlist[0].x < min_clip_x) &&
- (face->tvlist[1].x < min_clip_x) &&
- (face->tvlist[2].x < min_clip_x)) ||
- ((face->tvlist[0].x > max_clip_x) &&
- (face->tvlist[1].x > max_clip_x) &&
- (face->tvlist[2].x > max_clip_x)))
- return;
- // sort vertices
- if (face->tvlist[v1].y < face->tvlist[v0].y)
- {SWAP(v0,v1,temp);}
- if (face->tvlist[v2].y < face->tvlist[v0].y)
- {SWAP(v0,v2,temp);}
- if (face->tvlist[v2].y < face->tvlist[v1].y)
- {SWAP(v1,v2,temp);}
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_TOP;
- // sort vertices left to right
- if (face->tvlist[v1].x < face->tvlist[v0].x)
- {SWAP(v0,v1,temp);}
- } // end if
- else
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_BOTTOM;
- // sort vertices left to right
- if (face->tvlist[v2].x < face->tvlist[v1].x)
- {SWAP(v1,v2,temp);}
- } // end if
- else
- {
- // must be a general triangle
- tri_type = TRI_TYPE_GENERAL;
- } // end else
- // extract vertices for processing, now that we have order
- x0 = (int)(face->tvlist[v0].x+0.0);
- y0 = (int)(face->tvlist[v0].y+0.0);
- tu0 = (int)(face->tvlist[v0].u0);
- tv0 = (int)(face->tvlist[v0].v0);
- tz0 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- x1 = (int)(face->tvlist[v1].x+0.0);
- y1 = (int)(face->tvlist[v1].y+0.0);
- tu1 = (int)(face->tvlist[v1].u0);
- tv1 = (int)(face->tvlist[v1].v0);
- tz1 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- x2 = (int)(face->tvlist[v2].x+0.0);
- y2 = (int)(face->tvlist[v2].y+0.0);
- tu2 = (int)(face->tvlist[v2].u0);
- tv2 = (int)(face->tvlist[v2].v0);
- tz2 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // set interpolation restart value
- yrestart = y1;
- // what kind of triangle
- if (tri_type & TRI_TYPE_FLAT_MASK)
- {
- if (tri_type == TRI_TYPE_FLAT_TOP)
- {
- // compute all deltas
- dy = (y2 - y0);
- dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz2 - tz0) << 0)/dy;
- dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;
- dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz1) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz1 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x1 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- zl = (tz0 << 0);
- ur = (tu1 << FIXP16_SHIFT);
- vr = (tv1 << FIXP16_SHIFT);
- zr = (tz1 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end if flat top
- else
- {
- // must be flat bottom
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz1 - tz0) << 0)/dy;
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz0) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- zl = (tz0 << 0);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end else flat bottom
- // test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ????
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // reset vars
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if clip
- else
- {
- // non-clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ????
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
- vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
- zl = dzdyl*dyl + (tz1 << 0);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
- zr = dzdyr*dyr + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- zl = (tz0 << 0);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ???
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end if
- else
- {
- // no x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ????
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Textured_Triangle_INVZB_16
- ////////////////////////////////////////////////////////////////////////////////
- void Draw_Textured_Bilerp_TriangleINVZB_16(POLYF4DV2_PTR face, // ptr to face
- UCHAR *_dest_buffer, // pointer to video buffer
- int mem_pitch, // bytes per line, 320, 640 etc.
- UCHAR *_zbuffer, // pointer to z-buffer
- int zpitch) // bytes per line of zbuffer
- {
- // this function draws a textured triangle in 16-bit mode
- int v0=0,
- v1=1,
- v2=2,
- temp=0,
- tri_type = TRI_TYPE_NONE,
- irestart = INTERP_LHS;
- int dx,dy,dyl,dyr, // general deltas
- u,v,z,
- du,dv,dz,
- xi,yi, // the current interpolated x,y
- ui,vi,zi, // the current interpolated u,v,z
- index_x,index_y, // looping vars
- x,y, // hold general x,y
- xstart,
- xend,
- ystart,
- yrestart,
- yend,
- xl,
- dxdyl,
- xr,
- dxdyr,
- dudyl,
- ul,
- dvdyl,
- vl,
- dzdyl,
- zl,
- dudyr,
- ur,
- dvdyr,
- vr,
- dzdyr,
- zr;
- int x0,y0,tu0,tv0,tz0, // cached vertices
- x1,y1,tu1,tv1,tz1,
- x2,y2,tu2,tv2,tz2;
- USHORT *screen_ptr = NULL,
- *screen_line = NULL,
- *textmap = NULL,
- *dest_buffer = (USHORT *)_dest_buffer;
- UINT *z_ptr = NULL,
- *zbuffer = (UINT *)_zbuffer;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // extract texture map
- textmap = (USHORT *)face->texture->buffer;
- // extract base 2 of texture width
- int texture_shift2 = logbase2ofx[face->texture->width];
- // compute actual size of texture and store it
- int texture_size = face->texture->width-1;
- // adjust memory pitch to words, divide by 2
- mem_pitch >>=1;
- // adjust zbuffer pitch for 32 bit alignment
- zpitch >>= 2;
- // apply fill convention to coordinates
- face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
- // first trivial clipping rejection tests
- if (((face->tvlist[0].y < min_clip_y) &&
- (face->tvlist[1].y < min_clip_y) &&
- (face->tvlist[2].y < min_clip_y)) ||
- ((face->tvlist[0].y > max_clip_y) &&
- (face->tvlist[1].y > max_clip_y) &&
- (face->tvlist[2].y > max_clip_y)) ||
- ((face->tvlist[0].x < min_clip_x) &&
- (face->tvlist[1].x < min_clip_x) &&
- (face->tvlist[2].x < min_clip_x)) ||
- ((face->tvlist[0].x > max_clip_x) &&
- (face->tvlist[1].x > max_clip_x) &&
- (face->tvlist[2].x > max_clip_x)))
- return;
- // sort vertices
- if (face->tvlist[v1].y < face->tvlist[v0].y)
- {SWAP(v0,v1,temp);}
- if (face->tvlist[v2].y < face->tvlist[v0].y)
- {SWAP(v0,v2,temp);}
- if (face->tvlist[v2].y < face->tvlist[v1].y)
- {SWAP(v1,v2,temp);}
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_TOP;
- // sort vertices left to right
- if (face->tvlist[v1].x < face->tvlist[v0].x)
- {SWAP(v0,v1,temp);}
- } // end if
- else
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_BOTTOM;
- // sort vertices left to right
- if (face->tvlist[v2].x < face->tvlist[v1].x)
- {SWAP(v1,v2,temp);}
- } // end if
- else
- {
- // must be a general triangle
- tri_type = TRI_TYPE_GENERAL;
- } // end else
- // extract vertices for processing, now that we have order
- x0 = (int)(face->tvlist[v0].x+0.0);
- y0 = (int)(face->tvlist[v0].y+0.0);
- tu0 = (int)(face->tvlist[v0].u0);
- tv0 = (int)(face->tvlist[v0].v0);
- tz0 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- x1 = (int)(face->tvlist[v1].x+0.0);
- y1 = (int)(face->tvlist[v1].y+0.0);
- tu1 = (int)(face->tvlist[v1].u0);
- tv1 = (int)(face->tvlist[v1].v0);
- tz1 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- x2 = (int)(face->tvlist[v2].x+0.0);
- y2 = (int)(face->tvlist[v2].y+0.0);
- tu2 = (int)(face->tvlist[v2].u0);
- tv2 = (int)(face->tvlist[v2].v0);
- tz2 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // set interpolation restart value
- yrestart = y1;
- // what kind of triangle
- if (tri_type & TRI_TYPE_FLAT_MASK)
- {
- if (tri_type == TRI_TYPE_FLAT_TOP)
- {
- // compute all deltas
- dy = (y2 - y0);
- dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz2 - tz0) << 0)/dy;
- dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu1) << FIXP16_SHIFT)/dy;
- dvdyr = ((tv2 - tv1) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz1) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu1 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv1 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz1 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x1 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- zl = (tz0 << 0);
- ur = (tu1 << FIXP16_SHIFT);
- vr = (tv1 << FIXP16_SHIFT);
- zr = (tz1 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end if flat top
- else
- {
- // must be flat bottom
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dy;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dy;
- dzdyl = ((tz1 - tz0) << 0)/dy;
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dy;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dy;
- dzdyr = ((tz2 - tz0) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- zl = (tz0 << 0);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end else flat bottom
- // test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ????
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // reset vars
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // compute integral values of u,v
- int uint = ui >> FIXP16_SHIFT;
- int vint = vi >> FIXP16_SHIFT;
- int uint_pls_1 = uint+1;
- if (uint_pls_1 > texture_size) uint_pls_1 = texture_size;
- int vint_pls_1 = vint+1;
- if (vint_pls_1 > texture_size) vint_pls_1 = texture_size;
- int textel00 = textmap[(uint+0) + ((vint+0) << texture_shift2)];
- int textel10 = textmap[(uint_pls_1) + ((vint+0) << texture_shift2)];
- int textel01 = textmap[(uint+0) + ((vint_pls_1) << texture_shift2)];
- int textel11 = textmap[(uint_pls_1) + ((vint_pls_1) << texture_shift2)];
- // extract rgb components
- int r_textel00 = ((textel00 >> 11) );
- int g_textel00 = ((textel00 >> 5) & 0x3f);
- int b_textel00 = (textel00 & 0x1f);
- int r_textel10 = ((textel10 >> 11) );
- int g_textel10 = ((textel10 >> 5) & 0x3f);
- int b_textel10 = (textel10 & 0x1f);
- int r_textel01 = ((textel01 >> 11) );
- int g_textel01 = ((textel01 >> 5) & 0x3f);
- int b_textel01 = (textel01 & 0x1f);
- int r_textel11 = ((textel11 >> 11) );
- int g_textel11 = ((textel11 >> 5) & 0x3f);
- int b_textel11 = (textel11 & 0x1f);
- // compute fractional components of u,v in fixed 24.8 point format
- int dtu = (ui & (0xffff)) >> 8;
- int dtv = (vi & (0xffff)) >> 8;
- int one_minus_dtu = (1 << 8) - dtu;
- int one_minus_dtv = (1 << 8) - dtv;
- // each interpolant has 3 terms, (du), (dv), textel, however
- // the (du) and (dv) terms repeat during each computation of
- // r_textel, g_textel, and b_textel, so we can compute them once
- int one_minus_dtu_x_one_minus_dtv = (one_minus_dtu) * (one_minus_dtv);
- int dtu_x_one_minus_dtv = (dtu) * (one_minus_dtv);
- int dtu_x_dtv = (dtu) * (dtv);
- int one_minus_dtu_x_dtv = (one_minus_dtu) * (dtv);
- // now we are ready to sample the texture
- int r_textel = one_minus_dtu_x_one_minus_dtv * r_textel00 +
- dtu_x_one_minus_dtv * r_textel10 +
- dtu_x_dtv * r_textel11 +
- one_minus_dtu_x_dtv * r_textel01;
- int g_textel = one_minus_dtu_x_one_minus_dtv * g_textel00 +
- dtu_x_one_minus_dtv * g_textel10 +
- dtu_x_dtv * g_textel11 +
- one_minus_dtu_x_dtv * g_textel01;
- int b_textel = one_minus_dtu_x_one_minus_dtv * b_textel00 +
- dtu_x_one_minus_dtv * b_textel10 +
- dtu_x_dtv * b_textel11 +
- one_minus_dtu_x_dtv * b_textel01;
- // write textel
- screen_ptr[xi] = ((r_textel >> 16) << 11) + ((g_textel >> 16) << 5) + (b_textel >> 16);
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if clip
- else
- {
- // non-clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ????
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- // compute integral values of u,v
- int uint = ui >> FIXP16_SHIFT;
- int vint = vi >> FIXP16_SHIFT;
- int uint_pls_1 = uint+1;
- if (uint_pls_1 > texture_size) uint_pls_1 = texture_size;
- int vint_pls_1 = vint+1;
- if (vint_pls_1 > texture_size) vint_pls_1 = texture_size;
- int textel00 = textmap[(uint+0) + ((vint+0) << texture_shift2)];
- int textel10 = textmap[(uint_pls_1) + ((vint+0) << texture_shift2)];
- int textel01 = textmap[(uint+0) + ((vint_pls_1) << texture_shift2)];
- int textel11 = textmap[(uint_pls_1) + ((vint_pls_1) << texture_shift2)];
- // extract rgb components
- int r_textel00 = ((textel00 >> 11) );
- int g_textel00 = ((textel00 >> 5) & 0x3f);
- int b_textel00 = (textel00 & 0x1f);
- int r_textel10 = ((textel10 >> 11) );
- int g_textel10 = ((textel10 >> 5) & 0x3f);
- int b_textel10 = (textel10 & 0x1f);
- int r_textel01 = ((textel01 >> 11) );
- int g_textel01 = ((textel01 >> 5) & 0x3f);
- int b_textel01 = (textel01 & 0x1f);
- int r_textel11 = ((textel11 >> 11) );
- int g_textel11 = ((textel11 >> 5) & 0x3f);
- int b_textel11 = (textel11 & 0x1f);
- // compute fractional components of u,v in fixed 24.8 point format
- int dtu = (ui & (0xffff)) >> 8;
- int dtv = (vi & (0xffff)) >> 8;
- int one_minus_dtu = (1 << 8) - dtu;
- int one_minus_dtv = (1 << 8) - dtv;
- // each interpolant has 3 terms, (du), (dv), textel, however
- // the (du) and (dv) terms repeat during each computation of
- // r_textel, g_textel, and b_textel, so we can compute them once
- int one_minus_dtu_x_one_minus_dtv = (one_minus_dtu) * (one_minus_dtv);
- int dtu_x_one_minus_dtv = (dtu) * (one_minus_dtv);
- int dtu_x_dtv = (dtu) * (dtv);
- int one_minus_dtu_x_dtv = (one_minus_dtu) * (dtv);
- // now we are ready to sample the texture
- int r_textel = one_minus_dtu_x_one_minus_dtv * r_textel00 +
- dtu_x_one_minus_dtv * r_textel10 +
- dtu_x_dtv * r_textel11 +
- one_minus_dtu_x_dtv * r_textel01;
- int g_textel = one_minus_dtu_x_one_minus_dtv * g_textel00 +
- dtu_x_one_minus_dtv * g_textel10 +
- dtu_x_dtv * g_textel11 +
- one_minus_dtu_x_dtv * g_textel01;
- int b_textel = one_minus_dtu_x_one_minus_dtv * b_textel00 +
- dtu_x_one_minus_dtv * b_textel10 +
- dtu_x_dtv * b_textel11 +
- one_minus_dtu_x_dtv * b_textel01;
- // write textel
- screen_ptr[xi] = ((r_textel >> 16) << 11) + ((g_textel >> 16) << 5) + (b_textel >> 16);
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- ul = dudyl*dyl + (tu1 << FIXP16_SHIFT);
- vl = dvdyl*dyl + (tv1 << FIXP16_SHIFT);
- zl = dzdyl*dyl + (tz1 << 0);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- ur = dudyr*dyr + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dyr + (tv0 << FIXP16_SHIFT);
- zr = dzdyr*dyr + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << FIXP16_SHIFT);
- vl = dvdyl*dy + (tv0 << FIXP16_SHIFT);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << FIXP16_SHIFT);
- vr = dvdyr*dy + (tv0 << FIXP16_SHIFT);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv1 - tv0) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv2 - tv0) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << FIXP16_SHIFT);
- vl = (tv0 << FIXP16_SHIFT);
- zl = (tz0 << 0);
- ur = (tu0 << FIXP16_SHIFT);
- vr = (tv0 << FIXP16_SHIFT);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ???
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // compute integral values of u,v
- int uint = ui >> FIXP16_SHIFT;
- int vint = vi >> FIXP16_SHIFT;
- int uint_pls_1 = uint+1;
- if (uint_pls_1 > texture_size) uint_pls_1 = texture_size;
- int vint_pls_1 = vint+1;
- if (vint_pls_1 > texture_size) vint_pls_1 = texture_size;
- int textel00 = textmap[(uint+0) + ((vint+0) << texture_shift2)];
- int textel10 = textmap[(uint_pls_1) + ((vint+0) << texture_shift2)];
- int textel01 = textmap[(uint+0) + ((vint_pls_1) << texture_shift2)];
- int textel11 = textmap[(uint_pls_1) + ((vint_pls_1) << texture_shift2)];
- // extract rgb components
- int r_textel00 = ((textel00 >> 11) );
- int g_textel00 = ((textel00 >> 5) & 0x3f);
- int b_textel00 = (textel00 & 0x1f);
- int r_textel10 = ((textel10 >> 11) );
- int g_textel10 = ((textel10 >> 5) & 0x3f);
- int b_textel10 = (textel10 & 0x1f);
- int r_textel01 = ((textel01 >> 11) );
- int g_textel01 = ((textel01 >> 5) & 0x3f);
- int b_textel01 = (textel01 & 0x1f);
- int r_textel11 = ((textel11 >> 11) );
- int g_textel11 = ((textel11 >> 5) & 0x3f);
- int b_textel11 = (textel11 & 0x1f);
- // compute fractional components of u,v in fixed 24.8 point format
- int dtu = (ui & (0xffff)) >> 8;
- int dtv = (vi & (0xffff)) >> 8;
- int one_minus_dtu = (1 << 8) - dtu;
- int one_minus_dtv = (1 << 8) - dtv;
- // each interpolant has 3 terms, (du), (dv), textel, however
- // the (du) and (dv) terms repeat during each computation of
- // r_textel, g_textel, and b_textel, so we can compute them once
- int one_minus_dtu_x_one_minus_dtv = (one_minus_dtu) * (one_minus_dtv);
- int dtu_x_one_minus_dtv = (dtu) * (one_minus_dtv);
- int dtu_x_dtv = (dtu) * (dtv);
- int one_minus_dtu_x_dtv = (one_minus_dtu) * (dtv);
- // now we are ready to sample the texture
- int r_textel = one_minus_dtu_x_one_minus_dtv * r_textel00 +
- dtu_x_one_minus_dtv * r_textel10 +
- dtu_x_dtv * r_textel11 +
- one_minus_dtu_x_dtv * r_textel01;
- int g_textel = one_minus_dtu_x_one_minus_dtv * g_textel00 +
- dtu_x_one_minus_dtv * g_textel10 +
- dtu_x_dtv * g_textel11 +
- one_minus_dtu_x_dtv * g_textel01;
- int b_textel = one_minus_dtu_x_one_minus_dtv * b_textel00 +
- dtu_x_one_minus_dtv * b_textel10 +
- dtu_x_dtv * b_textel11 +
- one_minus_dtu_x_dtv * b_textel01;
- // write textel
- screen_ptr[xi] = ((r_textel >> 16) << 11) + ((g_textel >> 16) << 5) + (b_textel >> 16);
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end if
- else
- {
- // no x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- ui = ul + FIXP16_ROUND_UP;
- vi = vl + FIXP16_ROUND_UP;
- zi = zl;// + FIXP16_ROUND_UP; // ????
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul)/dx;
- dv = (vr - vl)/dx;
- dz = (zr - zl)/dx;
- } // end if
- else
- {
- du = (ur - ul);
- dv = (vr - vl);
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- // compute integral values of u,v
- int uint = ui >> FIXP16_SHIFT;
- int vint = vi >> FIXP16_SHIFT;
- int uint_pls_1 = uint+1;
- if (uint_pls_1 > texture_size) uint_pls_1 = texture_size;
- int vint_pls_1 = vint+1;
- if (vint_pls_1 > texture_size) vint_pls_1 = texture_size;
- int textel00 = textmap[(uint+0) + ((vint+0) << texture_shift2)];
- int textel10 = textmap[(uint_pls_1) + ((vint+0) << texture_shift2)];
- int textel01 = textmap[(uint+0) + ((vint_pls_1) << texture_shift2)];
- int textel11 = textmap[(uint_pls_1) + ((vint_pls_1) << texture_shift2)];
- // extract rgb components
- int r_textel00 = ((textel00 >> 11) );
- int g_textel00 = ((textel00 >> 5) & 0x3f);
- int b_textel00 = (textel00 & 0x1f);
- int r_textel10 = ((textel10 >> 11) );
- int g_textel10 = ((textel10 >> 5) & 0x3f);
- int b_textel10 = (textel10 & 0x1f);
- int r_textel01 = ((textel01 >> 11) );
- int g_textel01 = ((textel01 >> 5) & 0x3f);
- int b_textel01 = (textel01 & 0x1f);
- int r_textel11 = ((textel11 >> 11) );
- int g_textel11 = ((textel11 >> 5) & 0x3f);
- int b_textel11 = (textel11 & 0x1f);
- // compute fractional components of u,v in fixed 24.8 point format
- int dtu = (ui & (0xffff)) >> 8;
- int dtv = (vi & (0xffff)) >> 8;
- int one_minus_dtu = (1 << 8) - dtu;
- int one_minus_dtv = (1 << 8) - dtv;
- // each interpolant has 3 terms, (du), (dv), textel, however
- // the (du) and (dv) terms repeat during each computation of
- // r_textel, g_textel, and b_textel, so we can compute them once
- int one_minus_dtu_x_one_minus_dtv = (one_minus_dtu) * (one_minus_dtv);
- int dtu_x_one_minus_dtv = (dtu) * (one_minus_dtv);
- int dtu_x_dtv = (dtu) * (dtv);
- int one_minus_dtu_x_dtv = (one_minus_dtu) * (dtv);
- // now we are ready to sample the texture
- int r_textel = one_minus_dtu_x_one_minus_dtv * r_textel00 +
- dtu_x_one_minus_dtv * r_textel10 +
- dtu_x_dtv * r_textel11 +
- one_minus_dtu_x_dtv * r_textel01;
- int g_textel = one_minus_dtu_x_one_minus_dtv * g_textel00 +
- dtu_x_one_minus_dtv * g_textel10 +
- dtu_x_dtv * g_textel11 +
- one_minus_dtu_x_dtv * g_textel01;
- int b_textel = one_minus_dtu_x_one_minus_dtv * b_textel00 +
- dtu_x_one_minus_dtv * b_textel10 +
- dtu_x_dtv * b_textel11 +
- one_minus_dtu_x_dtv * b_textel01;
- // write textel
- screen_ptr[xi] = ((r_textel >> 16) << 11) + ((g_textel >> 16) << 5) + (b_textel >> 16);
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << FIXP16_SHIFT)/dyl;
- dvdyl = ((tv2 - tv1) << FIXP16_SHIFT)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << FIXP16_SHIFT);
- vl = (tv1 << FIXP16_SHIFT);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << FIXP16_SHIFT)/dyr;
- dvdyr = ((tv1 - tv2) << FIXP16_SHIFT)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << FIXP16_SHIFT);
- vr = (tv2 << FIXP16_SHIFT);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Textured_Bilerp_Triangle_INVZB_16
- ////////////////////////////////////////////////////////////////////////////////
- void Draw_Textured_Perspective_Triangle_INVZB_16(POLYF4DV2_PTR face, // ptr to face
- UCHAR *_dest_buffer, // pointer to video buffer
- int mem_pitch, // bytes per line, 320, 640 etc.
- UCHAR *_zbuffer, // pointer to z-buffer
- int zpitch) // bytes per line of zbuffer
- {
- // this function draws a textured triangle in 16-bit mode using a 1/z buffer and piecewise linear
- // perspective correct texture mappping, 1/z, u/z, v/z are interpolated down each edge then to draw
- // each span U and V are computed for each end point and the space is broken up into 32 pixel
- // spans where the correct U,V is computed at each point along the span, but linearly interpolated
- // across the span
- int v0=0,
- v1=1,
- v2=2,
- temp=0,
- tri_type = TRI_TYPE_NONE,
- irestart = INTERP_LHS;
- int dx,dy,dyl,dyr, // general deltas
- u,v,z,
- du,dv,dz,
- xi,yi, // the current interpolated x,y
- ui,vi,zi, // the current interpolated u,v,z
- index_x,index_y, // looping vars
- x,y, // hold general x,y
- xstart,
- xend,
- ystart,
- yrestart,
- yend,
- xl,
- dxdyl,
- xr,
- dxdyr,
- dudyl,
- ul,
- dvdyl,
- vl,
- dzdyl,
- zl,
- dudyr,
- ur,
- dvdyr,
- vr,
- dzdyr,
- zr;
- int x0,y0,tu0,tv0,tz0, // cached vertices
- x1,y1,tu1,tv1,tz1,
- x2,y2,tu2,tv2,tz2;
- USHORT *screen_ptr = NULL,
- *screen_line = NULL,
- *textmap = NULL,
- *dest_buffer = (USHORT *)_dest_buffer;
- UINT *z_ptr = NULL,
- *zbuffer = (UINT *)_zbuffer;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // extract texture map
- textmap = (USHORT *)face->texture->buffer;
- // extract base 2 of texture width
- int texture_shift2 = logbase2ofx[face->texture->width];
- // adjust memory pitch to words, divide by 2
- mem_pitch >>=1;
- // adjust zbuffer pitch for 32 bit alignment
- zpitch >>= 2;
- // apply fill convention to coordinates
- face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
- // first trivial clipping rejection tests
- if (((face->tvlist[0].y < min_clip_y) &&
- (face->tvlist[1].y < min_clip_y) &&
- (face->tvlist[2].y < min_clip_y)) ||
- ((face->tvlist[0].y > max_clip_y) &&
- (face->tvlist[1].y > max_clip_y) &&
- (face->tvlist[2].y > max_clip_y)) ||
- ((face->tvlist[0].x < min_clip_x) &&
- (face->tvlist[1].x < min_clip_x) &&
- (face->tvlist[2].x < min_clip_x)) ||
- ((face->tvlist[0].x > max_clip_x) &&
- (face->tvlist[1].x > max_clip_x) &&
- (face->tvlist[2].x > max_clip_x)))
- return;
- // sort vertices
- if (face->tvlist[v1].y < face->tvlist[v0].y)
- {SWAP(v0,v1,temp);}
- if (face->tvlist[v2].y < face->tvlist[v0].y)
- {SWAP(v0,v2,temp);}
- if (face->tvlist[v2].y < face->tvlist[v1].y)
- {SWAP(v1,v2,temp);}
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_TOP;
- // sort vertices left to right
- if (face->tvlist[v1].x < face->tvlist[v0].x)
- {SWAP(v0,v1,temp);}
- } // end if
- else
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_BOTTOM;
- // sort vertices left to right
- if (face->tvlist[v2].x < face->tvlist[v1].x)
- {SWAP(v1,v2,temp);}
- } // end if
- else
- {
- // must be a general triangle
- tri_type = TRI_TYPE_GENERAL;
- } // end else
- // extract vertices for processing, now that we have order
- x0 = (int)(face->tvlist[v0].x+0.0);
- y0 = (int)(face->tvlist[v0].y+0.0);
- tu0 = ((int)(face->tvlist[v0].u0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- tv0 = ((int)(face->tvlist[v0].v0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- tz0 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- x1 = (int)(face->tvlist[v1].x+0.0);
- y1 = (int)(face->tvlist[v1].y+0.0);
- tu1 = ((int)(face->tvlist[v1].u0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- tv1 = ((int)(face->tvlist[v1].v0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- tz1 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- x2 = (int)(face->tvlist[v2].x+0.0);
- y2 = (int)(face->tvlist[v2].y+0.0);
- tu2 = ((int)(face->tvlist[v2].u0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- tv2 = ((int)(face->tvlist[v2].v0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- tz2 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // set interpolation restart value
- yrestart = y1;
- // what kind of triangle
- if (tri_type & TRI_TYPE_FLAT_MASK)
- {
- if (tri_type == TRI_TYPE_FLAT_TOP)
- {
- // compute all deltas
- dy = (y2 - y0);
- dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu2 - tu0) << 0)/dy;
- dvdyl = ((tv2 - tv0) << 0)/dy;
- dzdyl = ((tz2 - tz0) << 0)/dy;
- dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu1) << 0)/dy;
- dvdyr = ((tv2 - tv1) << 0)/dy;
- dzdyr = ((tz2 - tz1) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << 0);
- vl = dvdyl*dy + (tv0 << 0);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu1 << 0);
- vr = dvdyr*dy + (tv1 << 0);
- zr = dzdyr*dy + (tz1 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x1 << FIXP16_SHIFT);
- ul = (tu0 << 0);
- vl = (tv0 << 0);
- zl = (tz0 << 0);
- ur = (tu1 << 0);
- vr = (tv1 << 0);
- zr = (tz1 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end if flat top
- else
- {
- // must be flat bottom
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu1 - tu0) << 0)/dy;
- dvdyl = ((tv1 - tv0) << 0)/dy;
- dzdyl = ((tz1 - tz0) << 0)/dy;
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu0) << 0)/dy;
- dvdyr = ((tv2 - tv0) << 0)/dy;
- dzdyr = ((tz2 - tz0) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << 0);
- vl = dvdyl*dy + (tv0 << 0);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << 0);
- vr = dvdyr*dy + (tv0 << 0);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << 0);
- vl = (tv0 << 0);
- zl = (tz0 << 0);
- ur = (tu0 << 0);
- vr = (tv0 << 0);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end else flat bottom
- // test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul + 0;
- vi = vl + 0;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul) / dx;
- dv = (vr - vl) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur - ul) ;
- dv = (vr - vl) ;
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // reset vars
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[ ((ui << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) + ( ((vi << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) << texture_shift2)];
- //screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if clip
- else
- {
- // non-clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul + 0;
- vi = vl + 0;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul) / dx;
- dv = (vr - vl) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur - ul) ;
- dv = (vr - vl) ;
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[ ((ui << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) + ( ((vi << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) << texture_shift2)];
- //screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << 0)/dyl;
- dvdyl = ((tv2 - tv1) << 0)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << 0)/dyr;
- dvdyr = ((tv2 - tv0) << 0)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- ul = dudyl*dyl + (tu1 << 0);
- vl = dvdyl*dyl + (tv1 << 0);
- zl = dzdyl*dyl + (tz1 << 0);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- ur = dudyr*dyr + (tu0 << 0);
- vr = dvdyr*dyr + (tv0 << 0);
- zr = dzdyr*dyr + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << 0)/dyl;
- dvdyl = ((tv1 - tv0) << 0)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << 0)/dyr;
- dvdyr = ((tv2 - tv0) << 0)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << 0);
- vl = dvdyl*dy + (tv0 << 0);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << 0);
- vr = dvdyr*dy + (tv0 << 0);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << 0)/dyl;
- dvdyl = ((tv1 - tv0) << 0)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << 0)/dyr;
- dvdyr = ((tv2 - tv0) << 0)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << 0);
- vl = (tv0 << 0);
- zl = (tz0 << 0);
- ur = (tu0 << 0);
- vr = (tv0 << 0);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul + 0;
- vi = vl + 0;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul) / dx;
- dv = (vr - vl) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur - ul) ;
- dv = (vr - vl) ;
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[ ((ui << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) + ( ((vi << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) << texture_shift2)];
- //screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << 0)/dyl;
- dvdyl = ((tv2 - tv1) << 0)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << 0);
- vl = (tv1 << 0);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << 0)/dyr;
- dvdyr = ((tv1 - tv2) << 0)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << 0);
- vr = (tv2 << 0);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end if
- else
- {
- // no x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul + 0;
- vi = vl + 0;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur - ul) / dx;
- dv = (vr - vl) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur - ul) ;
- dv = (vr - vl) ;
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[ ((ui << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) + ( ((vi << (FIXP28_SHIFT - FIXP22_SHIFT)) / zi) << texture_shift2)];
- //screen_ptr[xi] = textmap[(ui >> FIXP16_SHIFT) + ((vi >> FIXP16_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << 0)/dyl;
- dvdyl = ((tv2 - tv1) << 0)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << 0);
- vl = (tv1 << 0);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << 0)/dyr;
- dvdyr = ((tv1 - tv2) << 0)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << 0);
- vr = (tv2 << 0);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if
- } // end for y
- } // end else
- } // end if
- } // end Draw_Textured_Perspective_Triangle_INVZB_16
- ///////////////////////////////////////////////////////////////////////////////////
- void Draw_Textured_PerspectiveLP_Triangle_INVZB_16(POLYF4DV2_PTR face, // ptr to face
- UCHAR *_dest_buffer, // pointer to video buffer
- int mem_pitch, // bytes per line, 320, 640 etc.
- UCHAR *_zbuffer, // pointer to z-buffer
- int zpitch) // bytes per line of zbuffer
- {
- // this function draws a textured triangle in 16-bit mode using a 1/z buffer and piecewise linear
- // perspective correct texture mappping, 1/z, u/z, v/z are interpolated down each edge then to draw
- // each span U and V are computed for each end point and the space is broken up into 32 pixel
- // spans where the correct U,V is computed at each point along the span, but linearly interpolated
- // across the span
- int v0=0,
- v1=1,
- v2=2,
- temp=0,
- tri_type = TRI_TYPE_NONE,
- irestart = INTERP_LHS;
- int dx,dy,dyl,dyr, // general deltas
- u,v,z,
- du,dv,dz,
- xi,yi, // the current interpolated x,y
- ui,vi,zi, // the current interpolated u,v,z
- index_x,index_y, // looping vars
- x,y, // hold general x,y
- xstart,
- xend,
- ystart,
- yrestart,
- yend,
- xl,
- dxdyl,
- xr,
- dxdyr,
- dudyl,
- ul,
- dvdyl,
- vl,
- dzdyl,
- zl,
- dudyr,
- ur,
- dvdyr,
- vr,
- dzdyr,
- zr;
- int ul2, ur2, vl2, vr2;
- int x0,y0,tu0,tv0,tz0, // cached vertices
- x1,y1,tu1,tv1,tz1,
- x2,y2,tu2,tv2,tz2;
- USHORT *screen_ptr = NULL,
- *screen_line = NULL,
- *textmap = NULL,
- *dest_buffer = (USHORT *)_dest_buffer;
- UINT *z_ptr = NULL,
- *zbuffer = (UINT *)_zbuffer;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // extract texture map
- textmap = (USHORT *)face->texture->buffer;
- // extract base 2 of texture width
- int texture_shift2 = logbase2ofx[face->texture->width];
- // adjust memory pitch to words, divide by 2
- mem_pitch >>=1;
- // adjust zbuffer pitch for 32 bit alignment
- zpitch >>= 2;
- // apply fill convention to coordinates
- face->tvlist[0].x = (int)(face->tvlist[0].x+0.5);
- face->tvlist[0].y = (int)(face->tvlist[0].y+0.5);
- face->tvlist[1].x = (int)(face->tvlist[1].x+0.5);
- face->tvlist[1].y = (int)(face->tvlist[1].y+0.5);
- face->tvlist[2].x = (int)(face->tvlist[2].x+0.5);
- face->tvlist[2].y = (int)(face->tvlist[2].y+0.5);
- // first trivial clipping rejection tests
- if (((face->tvlist[0].y < min_clip_y) &&
- (face->tvlist[1].y < min_clip_y) &&
- (face->tvlist[2].y < min_clip_y)) ||
- ((face->tvlist[0].y > max_clip_y) &&
- (face->tvlist[1].y > max_clip_y) &&
- (face->tvlist[2].y > max_clip_y)) ||
- ((face->tvlist[0].x < min_clip_x) &&
- (face->tvlist[1].x < min_clip_x) &&
- (face->tvlist[2].x < min_clip_x)) ||
- ((face->tvlist[0].x > max_clip_x) &&
- (face->tvlist[1].x > max_clip_x) &&
- (face->tvlist[2].x > max_clip_x)))
- return;
- // sort vertices
- if (face->tvlist[v1].y < face->tvlist[v0].y)
- {SWAP(v0,v1,temp);}
- if (face->tvlist[v2].y < face->tvlist[v0].y)
- {SWAP(v0,v2,temp);}
- if (face->tvlist[v2].y < face->tvlist[v1].y)
- {SWAP(v1,v2,temp);}
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v0].y, face->tvlist[v1].y) )
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_TOP;
- // sort vertices left to right
- if (face->tvlist[v1].x < face->tvlist[v0].x)
- {SWAP(v0,v1,temp);}
- } // end if
- else
- // now test for trivial flat sided cases
- if (FCMP(face->tvlist[v1].y ,face->tvlist[v2].y))
- {
- // set triangle type
- tri_type = TRI_TYPE_FLAT_BOTTOM;
- // sort vertices left to right
- if (face->tvlist[v2].x < face->tvlist[v1].x)
- {SWAP(v1,v2,temp);}
- } // end if
- else
- {
- // must be a general triangle
- tri_type = TRI_TYPE_GENERAL;
- } // end else
- // extract vertices for processing, now that we have order
- x0 = (int)(face->tvlist[v0].x+0.0);
- y0 = (int)(face->tvlist[v0].y+0.0);
- tu0 = ((int)(face->tvlist[v0].u0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- tv0 = ((int)(face->tvlist[v0].v0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- tz0 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v0].z+0.5);
- x1 = (int)(face->tvlist[v1].x+0.0);
- y1 = (int)(face->tvlist[v1].y+0.0);
- tu1 = ((int)(face->tvlist[v1].u0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- tv1 = ((int)(face->tvlist[v1].v0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- tz1 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v1].z+0.5);
- x2 = (int)(face->tvlist[v2].x+0.0);
- y2 = (int)(face->tvlist[v2].y+0.0);
- tu2 = ((int)(face->tvlist[v2].u0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- tv2 = ((int)(face->tvlist[v2].v0+0.5) << FIXP22_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- tz2 = (1 << FIXP28_SHIFT) / (int)(face->tvlist[v2].z+0.5);
- // degenerate triangle
- if ( ((x0 == x1) && (x1 == x2)) || ((y0 == y1) && (y1 == y2)))
- return;
- // set interpolation restart value
- yrestart = y1;
- // what kind of triangle
- if (tri_type & TRI_TYPE_FLAT_MASK)
- {
- if (tri_type == TRI_TYPE_FLAT_TOP)
- {
- // compute all deltas
- dy = (y2 - y0);
- dxdyl = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu2 - tu0) << 0)/dy;
- dvdyl = ((tv2 - tv0) << 0)/dy;
- dzdyl = ((tz2 - tz0) << 0)/dy;
- dxdyr = ((x2 - x1) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu1) << 0)/dy;
- dvdyr = ((tv2 - tv1) << 0)/dy;
- dzdyr = ((tz2 - tz1) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << 0);
- vl = dvdyl*dy + (tv0 << 0);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x1 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu1 << 0);
- vr = dvdyr*dy + (tv1 << 0);
- zr = dzdyr*dy + (tz1 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x1 << FIXP16_SHIFT);
- ul = (tu0 << 0);
- vl = (tv0 << 0);
- zl = (tz0 << 0);
- ur = (tu1 << 0);
- vr = (tv1 << 0);
- zr = (tz1 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end if flat top
- else
- {
- // must be flat bottom
- // compute all deltas
- dy = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dy;
- dudyl = ((tu1 - tu0) << 0)/dy;
- dvdyl = ((tv1 - tv0) << 0)/dy;
- dzdyl = ((tz1 - tz0) << 0)/dy;
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dy;
- dudyr = ((tu2 - tu0) << 0)/dy;
- dvdyr = ((tv2 - tv0) << 0)/dy;
- dzdyr = ((tz2 - tz0) << 0)/dy;
- // test for y clipping
- if (y0 < min_clip_y)
- {
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << 0);
- vl = dvdyl*dy + (tv0 << 0);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << 0);
- vr = dvdyr*dy + (tv0 << 0);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- } // end if
- else
- {
- // no clipping
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << 0);
- vl = (tv0 << 0);
- zl = (tz0 << 0);
- ur = (tu0 << 0);
- vr = (tv0 << 0);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- } // end else
- } // end else flat bottom
- // test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute linear version of ul, ur, vl, vr
- ul2 = ((ul << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zl >> 6) ) << 16;
- ur2 = ((ur << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zr >> 6) ) << 16;
- vl2 = ((vl << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zl >> 6) ) << 16;
- vr2 = ((vr << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zr >> 6) ) << 16;
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul2 + 0;
- vi = vl2 + 0;
- dx = (xend - xstart);
- // compute u,v interpolants
- if ( dx > 0)
- {
- du = (ur2 - ul2) / dx;
- dv = (vr2 - vl2) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur2 - ul2) ;
- dv = (vr2 - vl2) ;
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // reset vars
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP22_SHIFT) + ((vi >> FIXP22_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if clip
- else
- {
- // non-clip version
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute linear version of ul, ur, vl, vr
- ul2 = ((ul << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zl >> 6) ) << 16;
- ur2 = ((ur << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zr >> 6) ) << 16;
- vl2 = ((vl << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zl >> 6) ) << 16;
- vr2 = ((vr << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zr >> 6) ) << 16;
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul2 + 0;
- vi = vl2 + 0;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur2 - ul2) / dx;
- dv = (vr2 - vl2) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur2 - ul2) ;
- dv = (vr2 - vl2) ;
- dz = (zr - zl);
- } // end else
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP22_SHIFT) + ((vi >> FIXP22_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- } // end for y
- } // end if non-clipped
- } // end if
- else
- if (tri_type==TRI_TYPE_GENERAL)
- {
- // first test for bottom clip, always
- if ((yend = y2) > max_clip_y)
- yend = max_clip_y;
- // pre-test y clipping status
- if (y1 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << 0)/dyl;
- dvdyl = ((tv2 - tv1) << 0)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << 0)/dyr;
- dvdyr = ((tv2 - tv0) << 0)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dyr = (min_clip_y - y0);
- dyl = (min_clip_y - y1);
- // computer new LHS starting values
- xl = dxdyl*dyl + (x1 << FIXP16_SHIFT);
- ul = dudyl*dyl + (tu1 << 0);
- vl = dvdyl*dyl + (tv1 << 0);
- zl = dzdyl*dyl + (tz1 << 0);
- // compute new RHS starting values
- xr = dxdyr*dyr + (x0 << FIXP16_SHIFT);
- ur = dudyr*dyr + (tu0 << 0);
- vr = dvdyr*dyr + (tv0 << 0);
- zr = dzdyr*dyr + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr > dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- if (y0 < min_clip_y)
- {
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << 0)/dyl;
- dvdyl = ((tv1 - tv0) << 0)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << 0)/dyr;
- dvdyr = ((tv2 - tv0) << 0)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // compute overclip
- dy = (min_clip_y - y0);
- // computer new LHS starting values
- xl = dxdyl*dy + (x0 << FIXP16_SHIFT);
- ul = dudyl*dy + (tu0 << 0);
- vl = dvdyl*dy + (tv0 << 0);
- zl = dzdyl*dy + (tz0 << 0);
- // compute new RHS starting values
- xr = dxdyr*dy + (x0 << FIXP16_SHIFT);
- ur = dudyr*dy + (tu0 << 0);
- vr = dvdyr*dy + (tv0 << 0);
- zr = dzdyr*dy + (tz0 << 0);
- // compute new starting y
- ystart = min_clip_y;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end if
- else
- {
- // no initial y clipping
- // compute all deltas
- // LHS
- dyl = (y1 - y0);
- dxdyl = ((x1 - x0) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu1 - tu0) << 0)/dyl;
- dvdyl = ((tv1 - tv0) << 0)/dyl;
- dzdyl = ((tz1 - tz0) << 0)/dyl;
- // RHS
- dyr = (y2 - y0);
- dxdyr = ((x2 - x0) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu2 - tu0) << 0)/dyr;
- dvdyr = ((tv2 - tv0) << 0)/dyr;
- dzdyr = ((tz2 - tz0) << 0)/dyr;
- // no clipping y
- // set starting values
- xl = (x0 << FIXP16_SHIFT);
- xr = (x0 << FIXP16_SHIFT);
- ul = (tu0 << 0);
- vl = (tv0 << 0);
- zl = (tz0 << 0);
- ur = (tu0 << 0);
- vr = (tv0 << 0);
- zr = (tz0 << 0);
- // set starting y
- ystart = y0;
- // test if we need swap to keep rendering left to right
- if (dxdyr < dxdyl)
- {
- SWAP(dxdyl,dxdyr,temp);
- SWAP(dudyl,dudyr,temp);
- SWAP(dvdyl,dvdyr,temp);
- SWAP(dzdyl,dzdyr,temp);
- SWAP(xl,xr,temp);
- SWAP(ul,ur,temp);
- SWAP(vl,vr,temp);
- SWAP(zl,zr,temp);
- SWAP(x1,x2,temp);
- SWAP(y1,y2,temp);
- SWAP(tu1,tu2,temp);
- SWAP(tv1,tv2,temp);
- SWAP(tz1,tz2,temp);
- // set interpolation restart
- irestart = INTERP_RHS;
- } // end if
- } // end else
- // test for horizontal clipping
- if ((x0 < min_clip_x) || (x0 > max_clip_x) ||
- (x1 < min_clip_x) || (x1 > max_clip_x) ||
- (x2 < min_clip_x) || (x2 > max_clip_x))
- {
- // clip version
- // x clipping
- // point screen ptr to starting line
- screen_ptr = dest_buffer + (ystart * mem_pitch);
- // point zbuffer to starting line
- z_ptr = zbuffer + (ystart * zpitch);
- for (yi = ystart; yi < yend; yi++)
- {
- // compute span endpoints
- xstart = ((xl + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- xend = ((xr + FIXP16_ROUND_UP) >> FIXP16_SHIFT);
- // compute linear version of ul, ur, vl, vr
- ul2 = ((ul << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zl >> 6) ) << 16;
- ur2 = ((ur << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zr >> 6) ) << 16;
- vl2 = ((vl << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zl >> 6) ) << 16;
- vr2 = ((vr << (FIXP28_SHIFT - FIXP22_SHIFT)) / (zr >> 6) ) << 16;
- // compute starting points for u,v interpolants
- zi = zl + 0; // ????
- ui = ul2 + 0;
- vi = vl2 + 0;
- // compute u,v interpolants
- if ((dx = (xend - xstart))>0)
- {
- du = (ur2 - ul2) / dx;
- dv = (vr2 - vl2) / dx;
- dz = (zr - zl) / dx;
- } // end if
- else
- {
- du = (ur2 - ul2) ;
- dv = (vr2 - vl2) ;
- dz = (zr - zl);
- } // end else
- ///////////////////////////////////////////////////////////////////////
- // test for x clipping, LHS
- if (xstart < min_clip_x)
- {
- // compute x overlap
- dx = min_clip_x - xstart;
- // slide interpolants over
- ui+=dx*du;
- vi+=dx*dv;
- zi+=dx*dz;
- // set x to left clip edge
- xstart = min_clip_x;
- } // end if
- // test for x clipping RHS
- if (xend > max_clip_x)
- xend = max_clip_x;
- ///////////////////////////////////////////////////////////////////////
- // draw span
- for (xi=xstart; xi < xend; xi++)
- {
- // test if z of current pixel is nearer than current z buffer value
- if (zi > z_ptr[xi])
- {
- // write textel
- screen_ptr[xi] = textmap[(ui >> FIXP22_SHIFT) + ((vi >> FIXP22_SHIFT) << texture_shift2)];
- // update z-buffer
- z_ptr[xi] = zi;
- } // end if
- // interpolate u,v,z
- ui+=du;
- vi+=dv;
- zi+=dz;
- } // end for xi
- // interpolate u,v,x along right and left edge
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- // advance screen ptr
- screen_ptr+=mem_pitch;
- // advance zbuffer ptr
- z_ptr+=zpitch;
- // test for yi hitting second region, if so change interpolant
- if (yi==yrestart)
- {
- // test interpolation side change flag
- if (irestart == INTERP_LHS)
- {
- // LHS
- dyl = (y2 - y1);
- dxdyl = ((x2 - x1) << FIXP16_SHIFT)/dyl;
- dudyl = ((tu2 - tu1) << 0)/dyl;
- dvdyl = ((tv2 - tv1) << 0)/dyl;
- dzdyl = ((tz2 - tz1) << 0)/dyl;
- // set starting values
- xl = (x1 << FIXP16_SHIFT);
- ul = (tu1 << 0);
- vl = (tv1 << 0);
- zl = (tz1 << 0);
- // interpolate down on LHS to even up
- xl+=dxdyl;
- ul+=dudyl;
- vl+=dvdyl;
- zl+=dzdyl;
- } // end if
- else
- {
- // RHS
- dyr = (y1 - y2);
- dxdyr = ((x1 - x2) << FIXP16_SHIFT)/dyr;
- dudyr = ((tu1 - tu2) << 0)/dyr;
- dvdyr = ((tv1 - tv2) << 0)/dyr;
- dzdyr = ((tz1 - tz2) << 0)/dyr;
- // set starting values
- xr = (x2 << FIXP16_SHIFT);
- ur = (tu2 << 0);
- vr = (tv2 << 0);
- zr = (tz2 << 0);
- // interpolate down on RHS to even up
- xr+=dxdyr;
- ur+=dudyr;
- vr+=dvdyr;
- zr+=dzdyr;
- } // end else
- } // end if