t3dlib1.cpp
资源名称:Source.rar [点击查看]
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:175k
源码类别:
游戏
开发平台:
Visual C++
- // finally write out the correct number of bits
- bitmap->bitmapinfoheader.biBitCount=16;
- // release working buffer
- free(temp_buffer);
- } // end if 24 bit
- else
- {
- // serious problem
- return(0);
- } // end else
- #if 0
- // write the file info out
- printf("nfilename:%s nsize=%d nwidth=%d nheight=%d nbitsperpixel=%d ncolors=%d nimpcolors=%d",
- filename,
- bitmap->bitmapinfoheader.biSizeImage,
- bitmap->bitmapinfoheader.biWidth,
- bitmap->bitmapinfoheader.biHeight,
- bitmap->bitmapinfoheader.biBitCount,
- bitmap->bitmapinfoheader.biClrUsed,
- bitmap->bitmapinfoheader.biClrImportant);
- #endif
- // close the file
- _lclose(file_handle);
- // flip the bitmap
- Flip_Bitmap(bitmap->buffer,
- bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8),
- bitmap->bitmapinfoheader.biHeight);
- // return success
- return(1);
- } // end Load_Bitmap_File
- ///////////////////////////////////////////////////////////
- int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
- {
- // this function releases all memory associated with "bitmap"
- if (bitmap->buffer)
- {
- // release memory
- free(bitmap->buffer);
- // reset pointer
- bitmap->buffer = NULL;
- } // end if
- // return success
- return(1);
- } // end Unload_Bitmap_File
- ///////////////////////////////////////////////////////////
- int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
- {
- // this function is used to flip bottom-up .BMP images
- UCHAR *buffer; // used to perform the image processing
- int index; // looping index
- // allocate the temporary buffer
- if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
- return(0);
- // copy image to work area
- memcpy(buffer,image,bytes_per_line*height);
- // flip vertically
- for (index=0; index < height; index++)
- memcpy(&image[((height-1) - index)*bytes_per_line],
- &buffer[index*bytes_per_line], bytes_per_line);
- // release the memory
- free(buffer);
- // return success
- return(1);
- } // end Flip_Bitmap
- ///////////////////////////////////////////////////////////
- void HLine16(int x1,int x2,int y,int color, UCHAR *vbuffer, int lpitch)
- {
- // draw a horizontal line using the memset function
- int temp; // used for temporary storage during endpoint swap
- USHORT *vbuffer2 = (USHORT *)vbuffer; // short pointer to buffer
- // convert pitch to words
- lpitch = lpitch >> 1;
- // perform trivial rejections
- if (y > max_clip_y || y < min_clip_y)
- return;
- // sort x1 and x2, so that x2 > x1
- if (x1>x2)
- {
- temp = x1;
- x1 = x2;
- x2 = temp;
- } // end swap
- // perform trivial rejections
- if (x1 > max_clip_x || x2 < min_clip_x)
- return;
- // now clip
- x1 = ((x1 < min_clip_x) ? min_clip_x : x1);
- x2 = ((x2 > max_clip_x) ? max_clip_x : x2);
- // draw the row of pixels
- Mem_Set_WORD((vbuffer2+(y*lpitch)+x1), color,x2-x1+1);
- } // end HLine16
- //////////////////////////////////////////////////////////////////////////////
- void VLine16(int y1,int y2,int x,int color,UCHAR *vbuffer, int lpitch)
- {
- // draw a vertical line, note that a memset function can no longer be
- // used since the pixel addresses are no longer contiguous in memory
- // note that the end points of the line must be on the screen
- USHORT *start_offset; // starting memory offset of line
- int index, // loop index
- temp; // used for temporary storage during swap
- // convert lpitch to number of words
- lpitch = lpitch >> 1;
- // perform trivial rejections
- if (x > max_clip_x || x < min_clip_x)
- return;
- // make sure y2 > y1
- if (y1>y2)
- {
- temp = y1;
- y1 = y2;
- y2 = temp;
- } // end swap
- // perform trivial rejections
- if (y1 > max_clip_y || y2 < min_clip_y)
- return;
- // now clip
- y1 = ((y1 < min_clip_y) ? min_clip_y : y1);
- y2 = ((y2 > max_clip_y) ? max_clip_y : y2);
- // compute starting position
- start_offset = (USHORT *)vbuffer + (y1*lpitch) + x;
- // draw line one pixel at a time
- for (index=0; index<=y2-y1; index++)
- {
- // set the pixel
- *start_offset = color;
- // move downward to next line
- start_offset+=lpitch;
- } // end for index
- } // end VLine16
- ///////////////////////////////////////////////////////////
- void HLine(int x1,int x2,int y,int color, UCHAR *vbuffer, int lpitch)
- {
- // draw a horizontal line using the memset function
- int temp; // used for temporary storage during endpoint swap
- // perform trivial rejections
- if (y > max_clip_y || y < min_clip_y)
- return;
- // sort x1 and x2, so that x2 > x1
- if (x1>x2)
- {
- temp = x1;
- x1 = x2;
- x2 = temp;
- } // end swap
- // perform trivial rejections
- if (x1 > max_clip_x || x2 < min_clip_x)
- return;
- // now clip
- x1 = ((x1 < min_clip_x) ? min_clip_x : x1);
- x2 = ((x2 > max_clip_x) ? max_clip_x : x2);
- // draw the row of pixels
- memset((UCHAR *)(vbuffer+(y*lpitch)+x1),
- (UCHAR)color,x2-x1+1);
- } // end HLine
- //////////////////////////////////////////////////////////////////////////////
- void VLine(int y1,int y2,int x,int color,UCHAR *vbuffer, int lpitch)
- {
- // draw a vertical line, note that a memset function can no longer be
- // used since the pixel addresses are no longer contiguous in memory
- // note that the end points of the line must be on the screen
- UCHAR *start_offset; // starting memory offset of line
- int index, // loop index
- temp; // used for temporary storage during swap
- // perform trivial rejections
- if (x > max_clip_x || x < min_clip_x)
- return;
- // make sure y2 > y1
- if (y1>y2)
- {
- temp = y1;
- y1 = y2;
- y2 = temp;
- } // end swap
- // perform trivial rejections
- if (y1 > max_clip_y || y2 < min_clip_y)
- return;
- // now clip
- y1 = ((y1 < min_clip_y) ? min_clip_y : y1);
- y2 = ((y2 > max_clip_y) ? max_clip_y : y2);
- // compute starting position
- start_offset = vbuffer + (y1*lpitch) + x;
- // draw line one pixel at a time
- for (index=0; index<=y2-y1; index++)
- {
- // set the pixel
- *start_offset = (UCHAR)color;
- // move downward to next line
- start_offset+=lpitch;
- } // end for index
- } // end VLine
- ///////////////////////////////////////////////////////////
- void Screen_Transitions(int effect, UCHAR *vbuffer, int lpitch)
- {
- // this function can be called to perform a myraid of screen transitions
- // to the destination buffer, make sure to save and restore the palette
- // when performing color transitions in 8-bit modes
- int pal_reg; // used as loop counter
- int index; // used as loop counter
- int red,green,blue; // used in fad algorithm
- PALETTEENTRY color; // temporary color
- PALETTEENTRY work_palette[MAX_COLORS_PALETTE]; // used as a working palette
- PALETTEENTRY work_color; // used in color algorithms
- // test which screen effect is being selected
- switch(effect)
- {
- case SCREEN_DARKNESS:
- {
- // fade to black
- for (index=0; index<80; index++)
- {
- // get the palette
- Save_Palette(work_palette);
- // process each color
- for (pal_reg=1; pal_reg<MAX_COLORS_PALETTE; pal_reg++)
- {
- // get the entry data
- color = work_palette[pal_reg];
- // test if this color register is already black
- if (color.peRed > 4) color.peRed-=3;
- else
- color.peRed = 0;
- if (color.peGreen > 4) color.peGreen-=3;
- else
- color.peGreen = 0;
- if (color.peBlue > 4) color.peBlue-=3;
- else
- color.peBlue = 0;
- // set the color to a diminished intensity
- work_palette[pal_reg] = color;
- } // end for pal_reg
- // write the palette back out
- Set_Palette(work_palette);
- // wait a bit
- Start_Clock(); Wait_Clock(12);
- } // end for index
- } break;
- case SCREEN_WHITENESS:
- {
- // fade to white
- for (index=0; index<64; index++)
- {
- // get the palette
- Save_Palette(work_palette);
- // loop thru all palette registers
- for (pal_reg=0; pal_reg < MAX_COLORS_PALETTE; pal_reg++)
- {
- // get the entry data
- color = work_palette[pal_reg];
- // make 32 bit copy of color
- red = color.peRed;
- green = color.peGreen;
- blue = color.peBlue;
- if ((red+=4) >=255)
- red=255;
- if ((green+=4) >=255)
- green=255;
- if ((blue+=4) >=255)
- blue=255;
- // store colors back
- color.peRed = red;
- color.peGreen = green;
- color.peBlue = blue;
- // set the color to a diminished intensity
- work_palette[pal_reg] = color;
- } // end for pal_reg
- // write the palette back out
- Set_Palette(work_palette);
- // wait a bit
- Start_Clock(); Wait_Clock(12);
- } // end for index
- } break;
- case SCREEN_REDNESS:
- {
- // fade to red
- for (index=0; index<64; index++)
- {
- // get the palette
- Save_Palette(work_palette);
- // loop thru all palette registers
- for (pal_reg=0; pal_reg < MAX_COLORS_PALETTE; pal_reg++)
- {
- // get the entry data
- color = work_palette[pal_reg];
- // make 32 bit copy of color
- red = color.peRed;
- green = color.peGreen;
- blue = color.peBlue;
- if ((red+=6) >=255)
- red=255;
- if ((green-=4) < 0)
- green=0;
- if ((blue-=4) < 0)
- blue=0;
- // store colors back
- color.peRed = red;
- color.peGreen = green;
- color.peBlue = blue;
- // set the color to a diminished intensity
- work_palette[pal_reg] = color;
- } // end for pal_reg
- // write the palette back out
- Set_Palette(work_palette);
- // wait a bit
- Start_Clock(); Wait_Clock(12);
- } // end for index
- } break;
- case SCREEN_BLUENESS:
- {
- // fade to blue
- for (index=0; index<64; index++)
- {
- // get the palette
- Save_Palette(work_palette);
- // loop thru all palette registers
- for (pal_reg=0; pal_reg < MAX_COLORS_PALETTE; pal_reg++)
- {
- // get the entry data
- color = work_palette[pal_reg];
- // make 32 bit copy of color
- red = color.peRed;
- green = color.peGreen;
- blue = color.peBlue;
- if ((red-=4) < 0)
- red=0;
- if ((green-=4) < 0)
- green=0;
- if ((blue+=6) >=255)
- blue=255;
- // store colors back
- color.peRed = red;
- color.peGreen = green;
- color.peBlue = blue;
- // set the color to a diminished intensity
- work_palette[pal_reg] = color;
- } // end for pal_reg
- // write the palette back out
- Set_Palette(work_palette);
- // wait a bit
- Start_Clock(); Wait_Clock(12);
- } // end for index
- } break;
- case SCREEN_GREENNESS:
- {
- // fade to green
- for (index=0; index<64; index++)
- {
- // get the palette
- Save_Palette(work_palette);
- // loop thru all palette registers
- for (pal_reg=0; pal_reg < MAX_COLORS_PALETTE; pal_reg++)
- {
- // get the entry data
- color = work_palette[pal_reg];
- // make 32 bit copy of color
- red = color.peRed;
- green = color.peGreen;
- blue = color.peBlue;
- if ((red-=4) < 0)
- red=0;
- if ((green+=6) >=255)
- green=255;
- if ((blue-=4) < 0)
- blue=0;
- // store colors back
- color.peRed = red;
- color.peGreen = green;
- color.peBlue = blue;
- // set the color to a diminished intensity
- work_palette[pal_reg] = color;
- } // end for pal_reg
- // write the palette back out
- Set_Palette(work_palette);
- // wait a bit
- Start_Clock(); Wait_Clock(12);
- } // end for index
- } break;
- case SCREEN_SWIPE_X:
- {
- // do a screen wipe from right to left, left to right
- for (index=0; index < (screen_width/2); index+=2)
- {
- // use this as a 1/70th of second time delay
- Start_Clock(); Wait_Clock(12);
- // test screen depth
- if (screen_bpp==8)
- {
- // draw two vertical lines at opposite ends of the screen
- VLine(0,(screen_height-1),(screen_width-1)-index,0,vbuffer,lpitch);
- VLine(0,(screen_height-1),index,0,vbuffer,lpitch);
- VLine(0,(screen_height-1),(screen_width-1)-(index+1),0,vbuffer,lpitch);
- VLine(0,(screen_height-1),index+1,0,vbuffer,lpitch);
- } // end if 8-bit mode
- else
- if (screen_bpp==16)
- {
- // 16-bit mode draw two vertical lines at opposite ends of the screen
- VLine16(0,(screen_height-1),(screen_width-1)-index,0,vbuffer,lpitch);
- VLine16(0,(screen_height-1),index,0,vbuffer,lpitch);
- VLine16(0,(screen_height-1),(screen_width-1)-(index+1),0,vbuffer,lpitch);
- VLine16(0,(screen_height-1),index+1,0,vbuffer,lpitch);
- } // end if 16-bit mode
- } // end for index
- } break;
- case SCREEN_SWIPE_Y:
- {
- // do a screen wipe from top to bottom, bottom to top
- for (index=0; index < (screen_height/2); index+=2)
- {
- // use this as a 1/70th of second time delay
- Start_Clock(); Wait_Clock(12);
- // test screen depth
- if (screen_bpp==8)
- {
- // draw two horizontal lines at opposite ends of the screen
- HLine(0,(screen_width-1),(screen_height-1)-index,0,vbuffer,lpitch);
- HLine(0,(screen_width-1),index,0,vbuffer,lpitch);
- HLine(0,(screen_width-1),(screen_height-1)-(index+1),0,vbuffer,lpitch);
- HLine(0,(screen_width-1),index+1,0,vbuffer,lpitch);
- } // end if 8-bit mode
- else
- if (screen_bpp==16)
- {
- // draw two horizontal lines at opposite ends of the screen
- HLine16(0,(screen_width-1),(screen_height-1)-index,0,vbuffer,lpitch);
- HLine16(0,(screen_width-1),index,0,vbuffer,lpitch);
- HLine16(0,(screen_width-1),(screen_height-1)-(index+1),0,vbuffer,lpitch);
- HLine16(0,(screen_width-1),index+1,0,vbuffer,lpitch);
- } // end if 16-bit mode
- } // end for index
- } break;
- case SCREEN_SCRUNCH:
- {
- // do a screen wipe from top to bottom, bottom to top
- for (index=0; index < (screen_width/2); index+=2)
- {
- // use this as a 1/70th of second time delay
- Start_Clock(); Wait_Clock(12);
- // test screen depth
- if (screen_bpp==8)
- {
- // draw two horizontal lines at opposite ends of the screen
- HLine(0,(screen_width-1),(screen_height-1)-index%(screen_height/2),0,vbuffer,lpitch);
- HLine(0,(screen_width-1),index%(screen_height/2),0,vbuffer,lpitch);
- HLine(0,(screen_width-1),(screen_height-1)-(index%(screen_height/2)+1),0,vbuffer,lpitch);
- HLine(0,(screen_width-1),index%(screen_height/2)+1,0,vbuffer,lpitch);
- // draw two vertical lines at opposite ends of the screen
- VLine(0,(screen_height-1),(screen_width-1)-index,0,vbuffer,lpitch);
- VLine(0,(screen_height-1),index,0,vbuffer,lpitch);
- VLine(0,(screen_height-1),(screen_width-1)-(index+1),0,vbuffer,lpitch);
- VLine(0,(screen_height-1),index+1,0,vbuffer,lpitch);
- } // end if 8-bit mode
- else
- // test screen depth
- if (screen_bpp==16)
- {
- // draw two horizontal lines at opposite ends of the screen
- HLine16(0,(screen_width-1),(screen_height-1)-index%(screen_height/2),0,vbuffer,lpitch);
- HLine16(0,(screen_width-1),index%(screen_height/2),0,vbuffer,lpitch);
- HLine16(0,(screen_width-1),(screen_height-1)-(index%(screen_height/2)+1),0,vbuffer,lpitch);
- HLine16(0,(screen_width-1),index%(screen_height/2)+1,0,vbuffer,lpitch);
- // draw two vertical lines at opposite ends of the screen
- VLine16(0,(screen_height-1),(screen_width-1)-index,0,vbuffer,lpitch);
- VLine16(0,(screen_height-1),index,0,vbuffer,lpitch);
- VLine16(0,(screen_height-1),(screen_width-1)-(index+1),0,vbuffer,lpitch);
- VLine16(0,(screen_height-1),index+1,0,vbuffer,lpitch);
- } // end if 8-bit mode
- } // end for index
- } break;
- case SCREEN_DISOLVE:
- {
- // disolve the screen by plotting zillions of little black dots
- if (screen_bpp==8)
- for (index=0; index<=screen_width*screen_height*4; index++)
- Draw_Pixel(rand()%screen_width,rand()%screen_height,0,vbuffer,lpitch);
- else
- if (screen_bpp==16)
- for (index=0; index<=screen_width*screen_height*4; index++)
- Draw_Pixel16(rand()%screen_width,rand()%screen_height,0,vbuffer,lpitch);
- } break;
- default:break;
- } // end switch
- } // end Screen_Transitions
- //////////////////////////////////////////////////////////////////////////////
- int Collision_Test(int x1, int y1, int w1, int h1,
- int x2, int y2, int w2, int h2)
- {
- // this function tests if the two rects overlap
- // get the radi of each rect
- int width1 = (w1>>1) - (w1>>3);
- int height1 = (h1>>1) - (h1>>3);
- int width2 = (w2>>1) - (w2>>3);
- int height2 = (h2>>1) - (h2>>3);
- // compute center of each rect
- int cx1 = x1 + width1;
- int cy1 = y1 + height1;
- int cx2 = x2 + width2;
- int cy2 = y2 + height2;
- // compute deltas
- int dx = abs(cx2 - cx1);
- int dy = abs(cy2 - cy1);
- // test if rects overlap
- if (dx < (width1+width2) && dy < (height1+height2))
- return(1);
- else
- // else no collision
- return(0);
- } // end Collision_Test
- ///////////////////////////////////////////////////////////
- int Color_Scan(int x1, int y1, int x2, int y2,
- UCHAR scan_start, UCHAR scan_end,
- UCHAR *scan_buffer, int scan_lpitch)
- {
- // this function implements a crude collision technique
- // based on scanning for a range of colors within a rectangle
- // clip rectangle
- // x coords first
- if (x1 >= screen_width)
- x1=screen_width-1;
- else
- if (x1 < 0)
- x1=0;
- if (x2 >= screen_width)
- x2=screen_width-1;
- else
- if (x2 < 0)
- x2=0;
- // now y-coords
- if (y1 >= screen_height)
- y1=screen_height-1;
- else
- if (y1 < 0)
- y1=0;
- if (y2 >= screen_height)
- y2=screen_height-1;
- else
- if (y2 < 0)
- y2=0;
- // scan the region
- scan_buffer +=y1*scan_lpitch;
- for (int scan_y=y1; scan_y<=y2; scan_y++)
- {
- for (int scan_x=x1; scan_x<=x2; scan_x++)
- {
- if (scan_buffer[scan_x] >= scan_start && scan_buffer[scan_x] <= scan_end )
- return(1);
- } // end for x
- // move down a line
- scan_buffer+=scan_lpitch;
- } // end for y
- // return failure
- return(0);
- } // end Color_Scan
- ////////////////////////////////////////////////////////////////
- int Color_Scan16(int x1, int y1, int x2, int y2,
- USHORT scan_start, USHORT scan_end,
- UCHAR *scan_buffer, int scan_lpitch)
- {
- // this function implements a crude collision technique
- // based on scanning for a range of colors within a rectangle
- // this is the 16-bit version, thus the interpretation of scan_start
- // and end are different, they are they EXACT RGB values you are looking
- // for, thus you can test for 2 values at most, else make them equal to
- // test for one value
- USHORT *scan_buffer2 = (USHORT *)scan_buffer;
- // convert number of bytes per line to number of 16-bit shorts
- scan_lpitch = (scan_lpitch >> 1);
- // clip rectangle
- // x coords first
- if (x1 >= screen_width)
- x1=screen_width-1;
- else
- if (x1 < 0)
- x1=0;
- if (x2 >= screen_width)
- x2=screen_width-1;
- else
- if (x2 < 0)
- x2=0;
- // now y-coords
- if (y1 >= screen_height)
- y1=screen_height-1;
- else
- if (y1 < 0)
- y1=0;
- if (y2 >= screen_height)
- y2=screen_height-1;
- else
- if (y2 < 0)
- y2=0;
- // scan the region
- scan_buffer2 +=y1*scan_lpitch;
- for (int scan_y=y1; scan_y<=y2; scan_y++)
- {
- for (int scan_x=x1; scan_x<=x2; scan_x++)
- {
- if (scan_buffer2[scan_x] == scan_start || scan_buffer2[scan_x] == scan_end )
- return(1);
- } // end for x
- // move down a line
- scan_buffer2+=scan_lpitch;
- } // end for y
- // return failure
- return(0);
- } // end Color_Scan16
- ////////////////////////////////////////////////////////////////
- int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, // bitmap file to scan image data from
- LPDIRECTDRAWSURFACE7 lpdds, // surface to hold data
- int cx,int cy) // cell to scan image from
- {
- // this function extracts a bitmap out of a bitmap file
- UCHAR *source_ptr, // working pointers
- *dest_ptr;
- DDSURFACEDESC2 ddsd; // direct draw surface description
- // get the addr to destination surface memory
- // set size of the structure
- ddsd.dwSize = sizeof(ddsd);
- // lock the display surface
- lpdds->Lock(NULL,
- &ddsd,
- DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
- NULL);
- // compute position to start scanning bits from
- cx = cx*(ddsd.dwWidth+1) + 1;
- cy = cy*(ddsd.dwHeight+1) + 1;
- // extract bitmap data
- source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;
- // assign a pointer to the memory surface for manipulation
- dest_ptr = (UCHAR *)ddsd.lpSurface;
- // iterate thru each scanline and copy bitmap
- for (int index_y=0; index_y < ddsd.dwHeight; index_y++)
- {
- // copy next line of data to destination
- memcpy(dest_ptr, source_ptr, ddsd.dwWidth);
- // advance pointers
- dest_ptr += (ddsd.lPitch);
- source_ptr += bitmap->bitmapinfoheader.biWidth;
- } // end for index_y
- // unlock the surface
- lpdds->Unlock(NULL);
- // return success
- return(1);
- } // end Scan_Image_Bitmap
- //////////////////////////////////////////////////////////////////////////////
- void Draw_Top_Tri(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle that has a flat top
- float dx_right, // the dx/dy ratio of the right edge of line
- dx_left, // the dx/dy ratio of the left edge of line
- xs,xe, // the starting and ending points of the edges
- height; // the height of the triangle
- int temp_x, // used during sorting as temps
- temp_y,
- right, // used by clipping
- left;
- // destination address of next scanline
- UCHAR *dest_addr = NULL;
- // test order of x1 and x2
- if (x2 < x1)
- {
- temp_x = x2;
- x2 = x1;
- x1 = temp_x;
- } // end if swap
- // compute delta's
- height = y3-y1;
- dx_left = (x3-x1)/height;
- dx_right = (x3-x2)/height;
- // set starting points
- xs = (float)x1;
- xe = (float)x2+(float)0.5;
- // perform y clipping
- if (y1 < min_clip_y)
- {
- // compute new xs and ys
- xs = xs+dx_left*(float)(-y1+min_clip_y);
- xe = xe+dx_right*(float)(-y1+min_clip_y);
- // reset y1
- y1=min_clip_y;
- } // end if top is off screen
- if (y3>max_clip_y)
- y3=max_clip_y;
- // compute starting address in video memory
- dest_addr = dest_buffer+y1*mempitch;
- // test if x clipping is needed
- if (x1>=min_clip_x && x1<=max_clip_x &&
- x2>=min_clip_x && x2<=max_clip_x &&
- x3>=min_clip_x && x3<=max_clip_x)
- {
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- memset((UCHAR *)dest_addr+(unsigned int)xs, color,(unsigned int)((int)xe-(int)xs+1));
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- } // end for
- } // end if no x clipping needed
- else
- {
- // clip x axis with slower version
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // do x clip
- left = (int)xs;
- right = (int)xe;
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- // clip line
- if (left < min_clip_x)
- {
- left = min_clip_x;
- if (right < min_clip_x)
- continue;
- }
- if (right > max_clip_x)
- {
- right = max_clip_x;
- if (left > max_clip_x)
- continue;
- }
- memset((UCHAR *)dest_addr+(unsigned int)left, color,(unsigned int)(right-left+1));
- } // end for
- } // end else x clipping needed
- } // end Draw_Top_Tri
- /////////////////////////////////////////////////////////////////////////////
- void Draw_Bottom_Tri(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle that has a flat bottom
- float dx_right, // the dx/dy ratio of the right edge of line
- dx_left, // the dx/dy ratio of the left edge of line
- xs,xe, // the starting and ending points of the edges
- height; // the height of the triangle
- int temp_x, // used during sorting as temps
- temp_y,
- right, // used by clipping
- left;
- // destination address of next scanline
- UCHAR *dest_addr;
- // test order of x1 and x2
- if (x3 < x2)
- {
- temp_x = x2;
- x2 = x3;
- x3 = temp_x;
- } // end if swap
- // compute delta's
- height = y3-y1;
- dx_left = (x2-x1)/height;
- dx_right = (x3-x1)/height;
- // set starting points
- xs = (float)x1;
- xe = (float)x1; // +(float)0.5;
- // perform y clipping
- if (y1<min_clip_y)
- {
- // compute new xs and ys
- xs = xs+dx_left*(float)(-y1+min_clip_y);
- xe = xe+dx_right*(float)(-y1+min_clip_y);
- // reset y1
- y1=min_clip_y;
- } // end if top is off screen
- if (y3>max_clip_y)
- y3=max_clip_y;
- // compute starting address in video memory
- dest_addr = dest_buffer+y1*mempitch;
- // test if x clipping is needed
- if (x1>=min_clip_x && x1<=max_clip_x &&
- x2>=min_clip_x && x2<=max_clip_x &&
- x3>=min_clip_x && x3<=max_clip_x)
- {
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- memset((UCHAR *)dest_addr+(unsigned int)xs, color,(unsigned int)((int)xe-(int)xs+1));
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- } // end for
- } // end if no x clipping needed
- else
- {
- // clip x axis with slower version
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // do x clip
- left = (int)xs;
- right = (int)xe;
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- // clip line
- if (left < min_clip_x)
- {
- left = min_clip_x;
- if (right < min_clip_x)
- continue;
- }
- if (right > max_clip_x)
- {
- right = max_clip_x;
- if (left > max_clip_x)
- continue;
- }
- memset((UCHAR *)dest_addr+(unsigned int)left, color,(unsigned int)(right-left+1));
- } // end for
- } // end else x clipping needed
- } // end Draw_Bottom_Tri
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Top_Tri16(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *_dest_buffer, int mempitch)
- {
- // this function draws a triangle that has a flat top
- float dx_right, // the dx/dy ratio of the right edge of line
- dx_left, // the dx/dy ratio of the left edge of line
- xs,xe, // the starting and ending points of the edges
- height; // the height of the triangle
- int temp_x, // used during sorting as temps
- temp_y,
- right, // used by clipping
- left;
- // cast dest buffer to ushort
- USHORT *dest_buffer = (USHORT *)_dest_buffer;
- // destination address of next scanline
- USHORT *dest_addr = NULL;
- // recompute mempitch in 16-bit words
- mempitch = (mempitch >> 1);
- // test order of x1 and x2
- if (x2 < x1)
- {
- temp_x = x2;
- x2 = x1;
- x1 = temp_x;
- } // end if swap
- // compute delta's
- height = y3-y1;
- dx_left = (x3-x1)/height;
- dx_right = (x3-x2)/height;
- // set starting points
- xs = (float)x1;
- xe = (float)x2; // +(float)0.5;
- // perform y clipping
- if (y1 < min_clip_y)
- {
- // compute new xs and ys
- xs = xs+dx_left*(float)(-y1+min_clip_y);
- xe = xe+dx_right*(float)(-y1+min_clip_y);
- // reset y1
- y1=min_clip_y;
- } // end if top is off screen
- if (y3>max_clip_y)
- y3=max_clip_y;
- // compute starting address in video memory
- dest_addr = dest_buffer+y1*mempitch;
- // test if x clipping is needed
- if (x1>=min_clip_x && x1<=max_clip_x &&
- x2>=min_clip_x && x2<=max_clip_x &&
- x3>=min_clip_x && x3<=max_clip_x)
- {
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // draw the line
- Mem_Set_WORD(dest_addr+(unsigned int)(xs),color,(unsigned int)((int)xe-(int)xs+1));
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- } // end for
- } // end if no x clipping needed
- else
- {
- // clip x axis with slower version
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // do x clip
- left = (int)xs;
- right = (int)xe;
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- // clip line
- if (left < min_clip_x)
- {
- left = min_clip_x;
- if (right < min_clip_x)
- continue;
- }
- if (right > max_clip_x)
- {
- right = max_clip_x;
- if (left > max_clip_x)
- continue;
- }
- // draw the line
- Mem_Set_WORD(dest_addr+(unsigned int)(left),color,(unsigned int)(right-left+1));
- } // end for
- } // end else x clipping needed
- } // end Draw_Top_Tri16
- /////////////////////////////////////////////////////////////////////////////
- void Draw_Bottom_Tri16(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *_dest_buffer, int mempitch)
- {
- // this function draws a triangle that has a flat bottom
- float dx_right, // the dx/dy ratio of the right edge of line
- dx_left, // the dx/dy ratio of the left edge of line
- xs,xe, // the starting and ending points of the edges
- height; // the height of the triangle
- int temp_x, // used during sorting as temps
- temp_y,
- right, // used by clipping
- left;
- // cast dest buffer to ushort
- USHORT *dest_buffer = (USHORT *)_dest_buffer;
- // destination address of next scanline
- USHORT *dest_addr = NULL;
- // recompute mempitch in 16-bit words
- mempitch = (mempitch >> 1);
- // test order of x1 and x2
- if (x3 < x2)
- {
- temp_x = x2;
- x2 = x3;
- x3 = temp_x;
- } // end if swap
- // compute delta's
- height = y3-y1;
- dx_left = (x2-x1)/height;
- dx_right = (x3-x1)/height;
- // set starting points
- xs = (float)x1;
- xe = (float)x1; // +(float)0.5;
- // perform y clipping
- if (y1 < min_clip_y)
- {
- // compute new xs and ys
- xs = xs+dx_left*(float)(-y1+min_clip_y);
- xe = xe+dx_right*(float)(-y1+min_clip_y);
- // reset y1
- y1 = min_clip_y;
- } // end if top is off screen
- if (y3 > max_clip_y)
- y3 = max_clip_y;
- // compute starting address in video memory
- dest_addr = dest_buffer+y1*mempitch;
- // test if x clipping is needed
- if (x1>=min_clip_x && x1<=max_clip_x &&
- x2>=min_clip_x && x2<=max_clip_x &&
- x3>=min_clip_x && x3<=max_clip_x)
- {
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // draw the line
- Mem_Set_WORD(dest_addr+(unsigned int)(xs),color,(unsigned int)((int)xe-(int)xs+1));
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- } // end for
- } // end if no x clipping needed
- else
- {
- // clip x axis with slower version
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // do x clip
- left = (int)xs;
- right = (int)xe;
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- // clip line
- if (left < min_clip_x)
- {
- left = min_clip_x;
- if (right < min_clip_x)
- continue;
- }
- if (right > max_clip_x)
- {
- right = max_clip_x;
- if (left > max_clip_x)
- continue;
- }
- // draw the line
- Mem_Set_WORD(dest_addr+(unsigned int)(left),color,(unsigned int)(right-left+1));
- } // end for
- } // end else x clipping needed
- } // end Draw_Bottom_Tri16
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_TriangleFP_2D(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle on the destination buffer using fixed point
- // it decomposes all triangles into a pair of flat top, flat bottom
- int temp_x, // used for sorting
- temp_y,
- new_x;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // test for h lines and v lines
- if ((x1==x2 && x2==x3) || (y1==y2 && y2==y3))
- return;
- // sort p1,p2,p3 in ascending y order
- if (y2<y1)
- {
- temp_x = x2;
- temp_y = y2;
- x2 = x1;
- y2 = y1;
- x1 = temp_x;
- y1 = temp_y;
- } // end if
- // now we know that p1 and p2 are in order
- if (y3<y1)
- {
- temp_x = x3;
- temp_y = y3;
- x3 = x1;
- y3 = y1;
- x1 = temp_x;
- y1 = temp_y;
- } // end if
- // finally test y3 against y2
- if (y3<y2)
- {
- temp_x = x3;
- temp_y = y3;
- x3 = x2;
- y3 = y2;
- x2 = temp_x;
- y2 = temp_y;
- } // end if
- // do trivial rejection tests for clipping
- if ( y3<min_clip_y || y1>max_clip_y ||
- (x1<min_clip_x && x2<min_clip_x && x3<min_clip_x) ||
- (x1>max_clip_x && x2>max_clip_x && x3>max_clip_x) )
- return;
- // test if top of triangle is flat
- if (y1==y2)
- {
- Draw_Top_TriFP(x1,y1,x2,y2,x3,y3,color, dest_buffer, mempitch);
- } // end if
- else
- if (y2==y3)
- {
- Draw_Bottom_TriFP(x1,y1,x2,y2,x3,y3,color, dest_buffer, mempitch);
- } // end if bottom is flat
- else
- {
- // general triangle that's needs to be broken up along long edge
- new_x = x1 + (int)(0.5+(float)(y2-y1)*(float)(x3-x1)/(float)(y3-y1));
- // draw each sub-triangle
- Draw_Bottom_TriFP(x1,y1,new_x,y2,x2,y2,color, dest_buffer, mempitch);
- Draw_Top_TriFP(x2,y2,new_x,y2,x3,y3,color, dest_buffer, mempitch);
- } // end else
- } // end Draw_TriangleFP_2D
- /////////////////////////////////////////////////////////////
- void Draw_Triangle_2D(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle on the destination buffer
- // it decomposes all triangles into a pair of flat top, flat bottom
- int temp_x, // used for sorting
- temp_y,
- new_x;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // test for h lines and v lines
- if ((x1==x2 && x2==x3) || (y1==y2 && y2==y3))
- return;
- // sort p1,p2,p3 in ascending y order
- if (y2<y1)
- {
- temp_x = x2;
- temp_y = y2;
- x2 = x1;
- y2 = y1;
- x1 = temp_x;
- y1 = temp_y;
- } // end if
- // now we know that p1 and p2 are in order
- if (y3<y1)
- {
- temp_x = x3;
- temp_y = y3;
- x3 = x1;
- y3 = y1;
- x1 = temp_x;
- y1 = temp_y;
- } // end if
- // finally test y3 against y2
- if (y3<y2)
- {
- temp_x = x3;
- temp_y = y3;
- x3 = x2;
- y3 = y2;
- x2 = temp_x;
- y2 = temp_y;
- } // end if
- // do trivial rejection tests for clipping
- if ( y3<min_clip_y || y1>max_clip_y ||
- (x1<min_clip_x && x2<min_clip_x && x3<min_clip_x) ||
- (x1>max_clip_x && x2>max_clip_x && x3>max_clip_x) )
- return;
- // test if top of triangle is flat
- if (y1==y2)
- {
- Draw_Top_Tri(x1,y1,x2,y2,x3,y3,color, dest_buffer, mempitch);
- } // end if
- else
- if (y2==y3)
- {
- Draw_Bottom_Tri(x1,y1,x2,y2,x3,y3,color, dest_buffer, mempitch);
- } // end if bottom is flat
- else
- {
- // general triangle that's needs to be broken up along long edge
- new_x = x1 + (int)(0.5+(float)(y2-y1)*(float)(x3-x1)/(float)(y3-y1));
- // draw each sub-triangle
- Draw_Bottom_Tri(x1,y1,new_x,y2,x2,y2,color, dest_buffer, mempitch);
- Draw_Top_Tri(x2,y2,new_x,y2,x3,y3,color, dest_buffer, mempitch);
- } // end else
- } // end Draw_Triangle_2D
- ///////////////////////////////////////////////////////////////////////////////
- void Draw_Triangle_2D16(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle on the destination buffer
- // it decomposes all triangles into a pair of flat top, flat bottom
- int temp_x, // used for sorting
- temp_y,
- new_x;
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // test for h lines and v lines
- if ((x1==x2 && x2==x3) || (y1==y2 && y2==y3))
- return;
- // sort p1,p2,p3 in ascending y order
- if (y2<y1)
- {
- temp_x = x2;
- temp_y = y2;
- x2 = x1;
- y2 = y1;
- x1 = temp_x;
- y1 = temp_y;
- } // end if
- // now we know that p1 and p2 are in order
- if (y3<y1)
- {
- temp_x = x3;
- temp_y = y3;
- x3 = x1;
- y3 = y1;
- x1 = temp_x;
- y1 = temp_y;
- } // end if
- // finally test y3 against y2
- if (y3<y2)
- {
- temp_x = x3;
- temp_y = y3;
- x3 = x2;
- y3 = y2;
- x2 = temp_x;
- y2 = temp_y;
- } // end if
- // do trivial rejection tests for clipping
- if ( y3<min_clip_y || y1>max_clip_y ||
- (x1<min_clip_x && x2<min_clip_x && x3<min_clip_x) ||
- (x1>max_clip_x && x2>max_clip_x && x3>max_clip_x) )
- return;
- // test if top of triangle is flat
- if (y1==y2)
- {
- Draw_Top_Tri16(x1,y1,x2,y2,x3,y3,color, dest_buffer, mempitch);
- } // end if
- else
- if (y2==y3)
- {
- Draw_Bottom_Tri16(x1,y1,x2,y2,x3,y3,color, dest_buffer, mempitch);
- } // end if bottom is flat
- else
- {
- // general triangle that's needs to be broken up along long edge
- new_x = x1 + (int)(0.5+(float)(y2-y1)*(float)(x3-x1)/(float)(y3-y1));
- // draw each sub-triangle
- Draw_Bottom_Tri16(x1,y1,new_x,y2,x2,y2,color, dest_buffer, mempitch);
- Draw_Top_Tri16(x2,y2,new_x,y2,x3,y3,color, dest_buffer, mempitch);
- } // end else
- } // end Draw_Triangle_2D16
- ////////////////////////////////////////////////////////////////////////////////
- #if 0
- inline void Draw_QuadFP_2D(int x0,int y0,
- int x1,int y1,
- int x2,int y2,
- int x3, int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a 2D quadrilateral
- // simply call the triangle function 2x, let it do all the work
- Draw_TriangleFP_2D(x0,y0,x1,y1,x3,y3,color,dest_buffer,mempitch);
- Draw_TriangleFP_2D(x1,y1,x2,y2,x3,y3,color,dest_buffer,mempitch);
- } // end Draw_QuadFP_2D
- #endif
- ////////////////////////////////////////////////////////////////////////////////
- void Draw_Top_TriFP(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle that has a flat top using fixed point math
- int dx_right, // the dx/dy ratio of the right edge of line
- dx_left, // the dx/dy ratio of the left edge of line
- xs,xe, // the starting and ending points of the edges
- height; // the height of the triangle
- int temp_x, // used during sorting as temps
- temp_y,
- right, // used by clipping
- left;
- UCHAR *dest_addr;
- // test for degenerate
- if (y1==y3 || y2==y3)
- return;
- // test order of x1 and x2
- if (x2 < x1)
- {
- temp_x = x2;
- x2 = x1;
- x1 = temp_x;
- } // end if swap
- // compute delta's
- height = y3-y1;
- dx_left = ((x3-x1)<<FIXP16_SHIFT)/height;
- dx_right = ((x3-x2)<<FIXP16_SHIFT)/height;
- // set starting points
- xs = (x1<<FIXP16_SHIFT);
- xe = (x2<<FIXP16_SHIFT);
- // perform y clipping
- if (y1<min_clip_y)
- {
- // compute new xs and ys
- xs = xs+dx_left*(-y1+min_clip_y);
- xe = xe+dx_right*(-y1+min_clip_y);
- // reset y1
- y1=min_clip_y;
- } // end if top is off screen
- if (y3>max_clip_y)
- y3=max_clip_y;
- // compute starting address in video memory
- dest_addr = dest_buffer+y1*mempitch;
- // test if x clipping is needed
- if (x1>=min_clip_x && x1<=max_clip_x &&
- x2>=min_clip_x && x2<=max_clip_x &&
- x3>=min_clip_x && x3<=max_clip_x)
- {
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- memset((UCHAR *)dest_addr+((xs+FIXP16_ROUND_UP)>>FIXP16_SHIFT),
- color, (((xe-xs+FIXP16_ROUND_UP)>>FIXP16_SHIFT)+1));
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- } // end for
- } // end if no x clipping needed
- else
- {
- // clip x axis with slower version
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // do x clip
- left = ((xs+FIXP16_ROUND_UP)>>16);
- right = ((xe+FIXP16_ROUND_UP)>>16);
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- // clip line
- if (left < min_clip_x)
- {
- left = min_clip_x;
- if (right < min_clip_x)
- continue;
- }
- if (right > max_clip_x)
- {
- right = max_clip_x;
- if (left > max_clip_x)
- continue;
- }
- memset((UCHAR *)dest_addr+(unsigned int)left,
- color,(unsigned int)(right-left+1));
- } // end for
- } // end else x clipping needed
- } // end Draw_Top_TriFP
- /////////////////////////////////////////////////////////////////////////////
- void Draw_Bottom_TriFP(int x1,int y1,
- int x2,int y2,
- int x3,int y3,
- int color,
- UCHAR *dest_buffer, int mempitch)
- {
- // this function draws a triangle that has a flat bottom using fixed point math
- int dx_right, // the dx/dy ratio of the right edge of line
- dx_left, // the dx/dy ratio of the left edge of line
- xs,xe, // the starting and ending points of the edges
- height; // the height of the triangle
- int temp_x, // used during sorting as temps
- temp_y,
- right, // used by clipping
- left;
- UCHAR *dest_addr;
- if (y1==y2 || y1==y3)
- return;
- // test order of x1 and x2
- if (x3 < x2)
- {
- temp_x = x2;
- x2 = x3;
- x3 = temp_x;
- } // end if swap
- // compute delta's
- height = y3-y1;
- dx_left = ((x2-x1)<<FIXP16_SHIFT)/height;
- dx_right = ((x3-x1)<<FIXP16_SHIFT)/height;
- // set starting points
- xs = (x1<<FIXP16_SHIFT);
- xe = (x1<<FIXP16_SHIFT);
- // perform y clipping
- if (y1<min_clip_y)
- {
- // compute new xs and ys
- xs = xs+dx_left*(-y1+min_clip_y);
- xe = xe+dx_right*(-y1+min_clip_y);
- // reset y1
- y1=min_clip_y;
- } // end if top is off screen
- if (y3>max_clip_y)
- y3=max_clip_y;
- // compute starting address in video memory
- dest_addr = dest_buffer+y1*mempitch;
- // test if x clipping is needed
- if (x1>=min_clip_x && x1<=max_clip_x &&
- x2>=min_clip_x && x2<=max_clip_x &&
- x3>=min_clip_x && x3<=max_clip_x)
- {
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- memset((UCHAR *)dest_addr+((xs+FIXP16_ROUND_UP)>>FIXP16_SHIFT),
- color, (((xe-xs+FIXP16_ROUND_UP)>>FIXP16_SHIFT)+1));
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- } // end for
- } // end if no x clipping needed
- else
- {
- // clip x axis with slower version
- // draw the triangle
- for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)
- {
- // do x clip
- left = ((xs+FIXP16_ROUND_UP)>>FIXP16_SHIFT);
- right = ((xe+FIXP16_ROUND_UP)>>FIXP16_SHIFT);
- // adjust starting point and ending point
- xs+=dx_left;
- xe+=dx_right;
- // clip line
- if (left < min_clip_x)
- {
- left = min_clip_x;
- if (right < min_clip_x)
- continue;
- }
- if (right > max_clip_x)
- {
- right = max_clip_x;
- if (left > max_clip_x)
- continue;
- }
- memset((UCHAR *)dest_addr+left,
- color, (right-left+1));
- } // end for
- } // end else x clipping needed
- } // end Draw_Bottom_TriFP
- ////////////////////////////////////////////////////////////////////////////
- int Fast_Distance_2D(int x, int y)
- {
- // this function computes the distance from 0,0 to x,y with 3.5% error
- // first compute the absolute value of x,y
- x = abs(x);
- y = abs(y);
- // compute the minimum of x,y
- int mn = MIN(x,y);
- // return the distance
- return(x+y-(mn>>1)-(mn>>2)+(mn>>4));
- } // end Fast_Distance_2D
- ///////////////////////////////////////////////////////////////////////////////
- float Fast_Distance_3D(float fx, float fy, float fz)
- {
- // this function computes the distance from the origin to x,y,z
- int temp; // used for swaping
- int x,y,z; // used for algorithm
- // make sure values are all positive
- x = fabs(fx) * 1024;
- y = fabs(fy) * 1024;
- z = fabs(fz) * 1024;
- // sort values
- if (y < x) SWAP(x,y,temp)
- if (z < y) SWAP(y,z,temp)
- if (y < x) SWAP(x,y,temp)
- int dist = (z + 11 * (y >> 5) + (x >> 2) );
- // compute distance with 8% error
- return((float)(dist >> 10));
- } // end Fast_Distance_3D
- ///////////////////////////////////////////////////////////////////////////////
- int Find_Bounding_Box_Poly2D(POLYGON2D_PTR poly,
- float &min_x, float &max_x,
- float &min_y, float &max_y)
- {
- // this function finds the bounding box of a 2D polygon
- // and returns the values in the sent vars
- // is this poly valid?
- if (poly->num_verts == 0)
- return(0);
- // initialize output vars (note they are pointers)
- // also note that the algorithm assumes local coordinates
- // that is, the poly verts are relative to 0,0
- max_x = max_y = min_x = min_y = 0;
- // process each vertex
- for (int index=0; index < poly->num_verts; index++)
- {
- // update vars - run min/max seek
- if (poly->vlist[index].x > max_x)
- max_x = poly->vlist[index].x;
- if (poly->vlist[index].x < min_x)
- min_x = poly->vlist[index].x;
- if (poly->vlist[index].y > max_y)
- max_y = poly->vlist[index].y;
- if (poly->vlist[index].y < min_y)
- min_y = poly->vlist[index].y;
- } // end for index
- // return success
- return(1);
- } // end Find_Bounding_Box_Poly2D
- ////////////////////////////////////////////////////////////////
- void Draw_Filled_Polygon2D(POLYGON2D_PTR poly, UCHAR *vbuffer, int mempitch)
- {
- // this function draws a general n sided polygon
- int ydiff1, ydiff2, // difference between starting x and ending x
- xdiff1, xdiff2, // difference between starting y and ending y
- start, // starting offset of line between edges
- length, // distance from edge 1 to edge 2
- errorterm1, errorterm2, // error terms for edges 1 & 2
- offset1, offset2, // offset of current pixel in edges 1 & 2
- count1, count2, // increment count for edges 1 & 2
- xunit1, xunit2; // unit to advance x offset for edges 1 & 2
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // initialize count of number of edges drawn:
- int edgecount = poly->num_verts-1;
- // determine which vertex is at top of polygon:
- int firstvert=0; // start by assuming vertex 0 is at top
- int min_y=poly->vlist[0].y; // find y coordinate of vertex 0
- for (int index=1; index < poly->num_verts; index++)
- {
- // Search thru vertices
- if ((poly->vlist[index].y) < min_y)
- {
- // is another vertex higher?
- firstvert=index;
- min_y=poly->vlist[index].y;
- } // end if
- } // end for index
- // finding starting and ending vertices of first two edges:
- int startvert1=firstvert; // get starting vertex of edge 1
- int startvert2=firstvert; // get starting vertex of edge 2
- int xstart1=poly->vlist[startvert1].x+poly->x0;
- int ystart1=poly->vlist[startvert1].y+poly->y0;
- int xstart2=poly->vlist[startvert2].x+poly->x0;
- int ystart2=poly->vlist[startvert2].y+poly->y0;
- int endvert1=startvert1-1; // get ending vertex of edge 1
- if (endvert1 < 0)
- endvert1=poly->num_verts-1; // check for wrap
- int xend1=poly->vlist[endvert1].x+poly->x0; // get x & y coordinates
- int yend1=poly->vlist[endvert1].y+poly->y0; // of ending vertices
- int endvert2=startvert2+1; // get ending vertex of edge 2
- if (endvert2==(poly->num_verts))
- endvert2=0; // Check for wrap
- int xend2=poly->vlist[endvert2].x+poly->x0; // get x & y coordinates
- int yend2=poly->vlist[endvert2].y+poly->y0; // of ending vertices
- // draw the polygon:
- while (edgecount>0)
- {
- // continue drawing until all edges drawn
- offset1=mempitch*ystart1+xstart1; // offset of edge 1
- offset2=mempitch*ystart2+xstart2; // offset of edge 2
- // initialize error terms
- // for edges 1 & 2
- errorterm1=0;
- errorterm2=0;
- // get absolute value of
- if ((ydiff1=yend1-ystart1) < 0)
- ydiff1=-ydiff1;
- // x & y lengths of edges
- if ((ydiff2=yend2-ystart2) < 0)
- ydiff2=-ydiff2;
- if ((xdiff1=xend1-xstart1) < 0)
- {
- // get value of length
- xunit1=-1; // calculate X increment
- xdiff1=-xdiff1;
- } // end if
- else
- {
- xunit1=1;
- } // end else
- if ((xdiff2=xend2-xstart2) < 0)
- {
- // Get value of length
- xunit2=-1; // calculate X increment
- xdiff2=-xdiff2;
- } // end else
- else
- {
- xunit2=1;
- } // end else
- // choose which of four routines to use
- if (xdiff1 > ydiff1)
- {
- // if x length of edge 1 is greater than y length
- if (xdiff2 > ydiff2)
- {
- // if X length of edge 2 is greater than y length
- // increment edge 1 on X and edge 2 on X:
- count1=xdiff1; // count for x increment on edge 1
- count2=xdiff2; // count for x increment on edge 2
- while (count1 && count2)
- {
- // continue drawing until one edge is done
- // calculate edge 1:
- while ((errorterm1 < xdiff1) && (count1 > 0))
- {
- // finished w/edge 1?
- if (count1--)
- {
- // count down on edge 1
- offset1+=xunit1; // increment pixel offset
- xstart1+=xunit1;
- } // end if
- errorterm1+=ydiff1; // increment error term
- if (errorterm1 < xdiff1)
- { // if not more than XDIFF
- vbuffer[offset1]=(UCHAR)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm1-=xdiff1; // if time to increment X, restore error term
- // calculate edge 2:
- while ((errorterm2 < xdiff2) && (count2 > 0))
- {
- // finished w/edge 2?
- if (count2--)
- {
- // count down on edge 2
- offset2+=xunit2; // increment pixel offset
- xstart2+=xunit2;
- } // end if
- errorterm2+=ydiff2; // increment error term
- if (errorterm2 < xdiff2)
- { // if not more than XDIFF
- vbuffer[offset2]=(UCHAR)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm2-=xdiff2; // if time to increment X, restore error term
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- { // if negative...
- length=-length; // make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++)
- { // From edge to edge...
- vbuffer[index]=(UCHAR)poly->color; // ...draw the line
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end if
- } // end if
- else
- {
- // increment edge 1 on X and edge 2 on Y:
- count1=xdiff1; // count for X increment on edge 1
- count2=ydiff2; // count for Y increment on edge 2
- while (count1 && count2)
- { // continue drawing until one edge is done
- // calculate edge 1:
- while ((errorterm1 < xdiff1) && (count1 > 0))
- { // finished w/edge 1?
- if (count1--)
- {
- // count down on edge 1
- offset1+=xunit1; // increment pixel offset
- xstart1+=xunit1;
- } // end if
- errorterm1+=ydiff1; // increment error term
- if (errorterm1 < xdiff1)
- { // If not more than XDIFF
- vbuffer[offset1]=(UCHAR)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm1-=xdiff1; // If time to increment X, restore error term
- // calculate edge 2:
- errorterm2+=xdiff2; // increment error term
- if (errorterm2 >= ydiff2)
- { // if time to increment Y...
- errorterm2-=ydiff2; // ...restore error term
- offset2+=xunit2; // ...and advance offset to next pixel
- xstart2+=xunit2;
- } // end if
- count2--;
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- { // if negative...
- length=-length; // ...make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++) // from edge to edge
- {
- vbuffer[index]=(UCHAR)poly->color; // ...draw the line
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end while
- } // end if
- } // end if
- else
- {
- if (xdiff2 > ydiff2)
- {
- // increment edge 1 on Y and edge 2 on X:
- count1=ydiff1; // count for Y increment on edge 1
- count2=xdiff2; // count for X increment on edge 2
- while(count1 && count2)
- { // continue drawing until one edge is done
- // calculate edge 1:
- errorterm1+=xdiff1; // Increment error term
- if (errorterm1 >= ydiff1)
- { // if time to increment Y...
- errorterm1-=ydiff1; // ...restore error term
- offset1+=xunit1; // ...and advance offset to next pixel
- xstart1+=xunit1;
- } // end if
- count1--;
- // Calculate edge 2:
- while ((errorterm2 < xdiff2) && (count2 > 0))
- { // finished w/edge 1?
- if (count2--)
- { // count down on edge 2
- offset2+=xunit2; // increment pixel offset
- xstart2+=xunit2;
- } // end if
- errorterm2+=ydiff2; // increment error term
- if (errorterm2 < xdiff2)
- { // if not more than XDIFF
- vbuffer[offset2]=(UCHAR)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm2-=xdiff2; // if time to increment X, restore error term
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- { // if negative...
- length=-length; // ...make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++) // from edge to edge...
- {
- vbuffer[index]=(UCHAR)poly->color; // ...draw the line
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end if
- } // end if
- else
- {
- // increment edge 1 on Y and edge 2 on Y:
- count1=ydiff1; // count for Y increment on edge 1
- count2=ydiff2; // count for Y increment on edge 2
- while(count1 && count2)
- {
- // continue drawing until one edge is done
- // calculate edge 1:
- errorterm1+=xdiff1; // increment error term
- if (errorterm1 >= ydiff1)
- { // if time to increment Y
- errorterm1-=ydiff1; // ...restore error term
- offset1+=xunit1; // ...and advance offset to next pixel
- xstart1+=xunit1;
- } // end if
- count1--;
- // calculate edge 2:
- errorterm2+=xdiff2; // increment error term
- if (errorterm2 >= ydiff2)
- { // if time to increment Y
- errorterm2-=ydiff2; // ...restore error term
- offset2+=xunit2; // ...and advance offset to next pixel
- xstart2+=xunit2;
- } // end if
- --count2;
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- {
- // if negative...
- length=-length; // ...make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++)
- { // from edge to edge
- vbuffer[index]=(UCHAR)poly->color; // ...draw the linee
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end while
- } // end else
- } // end if
- // another edge (at least) is complete. Start next edge, if any.
- if (!count1)
- { // if edge 1 is complete...
- --edgecount; // decrement the edge count
- startvert1=endvert1; // make ending vertex into start vertex
- --endvert1; // and get new ending vertex
- if (endvert1 < 0)
- endvert1=poly->num_verts-1; // check for wrap
- xend1=poly->vlist[endvert1].x+poly->x0; // get x & y of new end vertex
- yend1=poly->vlist[endvert1].y+poly->y0;
- } // end if
- if (!count2)
- { // if edge 2 is complete...
- --edgecount; // decrement the edge count
- startvert2=endvert2; // make ending vertex into start vertex
- endvert2++; // and get new ending vertex
- if (endvert2==(poly->num_verts))
- endvert2=0; // check for wrap
- xend2=poly->vlist[endvert2].x+poly->x0; // get x & y of new end vertex
- yend2=poly->vlist[endvert2].y+poly->y0;
- } // end if
- } // end while
- } // end Draw_Filled_Polygon2D
- ///////////////////////////////////////////////////////////////
- void Draw_Filled_Polygon2D16(POLYGON2D_PTR poly, UCHAR *_vbuffer, int mempitch)
- {
- // this function draws a general n sided polygon
- int ydiff1, ydiff2, // difference between starting x and ending x
- xdiff1, xdiff2, // difference between starting y and ending y
- start, // starting offset of line between edges
- length, // distance from edge 1 to edge 2
- errorterm1, errorterm2, // error terms for edges 1 & 2
- offset1, offset2, // offset of current pixel in edges 1 & 2
- count1, count2, // increment count for edges 1 & 2
- xunit1, xunit2; // unit to advance x offset for edges 1 & 2
- #ifdef DEBUG_ON
- // track rendering stats
- debug_polys_rendered_per_frame++;
- #endif
- // recast vbuffer into short version since this is a 16 bit mode
- USHORT *vbuffer = (USHORT *)_vbuffer;
- // convert mempitch into WORD or 16bit stride
- mempitch = (mempitch >> 1);
- // initialize count of number of edges drawn:
- int edgecount = poly->num_verts-1;
- // determine which vertex is at top of polygon:
- int firstvert=0; // start by assuming vertex 0 is at top
- int min_y=poly->vlist[0].y; // find y coordinate of vertex 0
- for (int index=1; index < poly->num_verts; index++)
- {
- // Search thru vertices
- if ((poly->vlist[index].y) < min_y)
- {
- // is another vertex higher?
- firstvert=index;
- min_y=poly->vlist[index].y;
- } // end if
- } // end for index
- // finding starting and ending vertices of first two edges:
- int startvert1=firstvert; // get starting vertex of edge 1
- int startvert2=firstvert; // get starting vertex of edge 2
- int xstart1=poly->vlist[startvert1].x+poly->x0;
- int ystart1=poly->vlist[startvert1].y+poly->y0;
- int xstart2=poly->vlist[startvert2].x+poly->x0;
- int ystart2=poly->vlist[startvert2].y+poly->y0;
- int endvert1=startvert1-1; // get ending vertex of edge 1
- if (endvert1 < 0)
- endvert1=poly->num_verts-1; // check for wrap
- int xend1=poly->vlist[endvert1].x+poly->x0; // get x & y coordinates
- int yend1=poly->vlist[endvert1].y+poly->y0; // of ending vertices
- int endvert2=startvert2+1; // get ending vertex of edge 2
- if (endvert2==(poly->num_verts))
- endvert2=0; // Check for wrap
- int xend2=poly->vlist[endvert2].x+poly->x0; // get x & y coordinates
- int yend2=poly->vlist[endvert2].y+poly->y0; // of ending vertices
- // draw the polygon:
- while (edgecount>0)
- {
- // continue drawing until all edges drawn
- offset1=mempitch*ystart1+xstart1; // offset of edge 1
- offset2=mempitch*ystart2+xstart2; // offset of edge 2
- // initialize error terms
- // for edges 1 & 2
- errorterm1=0;
- errorterm2=0;
- // get absolute value of
- if ((ydiff1=yend1-ystart1) < 0)
- ydiff1=-ydiff1;
- // x & y lengths of edges
- if ((ydiff2=yend2-ystart2) < 0)
- ydiff2=-ydiff2;
- if ((xdiff1=xend1-xstart1) < 0)
- {
- // get value of length
- xunit1=-1; // calculate X increment
- xdiff1=-xdiff1;
- } // end if
- else
- {
- xunit1=1;
- } // end else
- if ((xdiff2=xend2-xstart2) < 0)
- {
- // Get value of length
- xunit2=-1; // calculate X increment
- xdiff2=-xdiff2;
- } // end else
- else
- {
- xunit2=1;
- } // end else
- // choose which of four routines to use
- if (xdiff1 > ydiff1)
- {
- // if x length of edge 1 is greater than y length
- if (xdiff2 > ydiff2)
- {
- // if X length of edge 2 is greater than y length
- // increment edge 1 on X and edge 2 on X:
- count1=xdiff1; // count for x increment on edge 1
- count2=xdiff2; // count for x increment on edge 2
- while (count1 && count2)
- {
- // continue drawing until one edge is done
- // calculate edge 1:
- while ((errorterm1 < xdiff1) && (count1 > 0))
- {
- // finished w/edge 1?
- if (count1--)
- {
- // count down on edge 1
- offset1+=xunit1; // increment pixel offset
- xstart1+=xunit1;
- } // end if
- errorterm1+=ydiff1; // increment error term
- if (errorterm1 < xdiff1)
- { // if not more than XDIFF
- vbuffer[offset1]=(USHORT)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm1-=xdiff1; // if time to increment X, restore error term
- // calculate edge 2:
- while ((errorterm2 < xdiff2) && (count2 > 0))
- {
- // finished w/edge 2?
- if (count2--)
- {
- // count down on edge 2
- offset2+=xunit2; // increment pixel offset
- xstart2+=xunit2;
- } // end if
- errorterm2+=ydiff2; // increment error term
- if (errorterm2 < xdiff2)
- { // if not more than XDIFF
- vbuffer[offset2]=(USHORT)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm2-=xdiff2; // if time to increment X, restore error term
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- { // if negative...
- length=-length; // make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++)
- { // From edge to edge...
- vbuffer[index]=(USHORT)poly->color; // ...draw the line
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end if
- } // end if
- else
- {
- // increment edge 1 on X and edge 2 on Y:
- count1=xdiff1; // count for X increment on edge 1
- count2=ydiff2; // count for Y increment on edge 2
- while (count1 && count2)
- { // continue drawing until one edge is done
- // calculate edge 1:
- while ((errorterm1 < xdiff1) && (count1 > 0))
- { // finished w/edge 1?
- if (count1--)
- {
- // count down on edge 1
- offset1+=xunit1; // increment pixel offset
- xstart1+=xunit1;
- } // end if
- errorterm1+=ydiff1; // increment error term
- if (errorterm1 < xdiff1)
- { // If not more than XDIFF
- vbuffer[offset1]=(USHORT)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm1-=xdiff1; // If time to increment X, restore error term
- // calculate edge 2:
- errorterm2+=xdiff2; // increment error term
- if (errorterm2 >= ydiff2)
- { // if time to increment Y...
- errorterm2-=ydiff2; // ...restore error term
- offset2+=xunit2; // ...and advance offset to next pixel
- xstart2+=xunit2;
- } // end if
- count2--;
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- { // if negative...
- length=-length; // ...make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++) // from edge to edge
- {
- vbuffer[index]=(USHORT)poly->color; // ...draw the line
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end while
- } // end if
- } // end if
- else
- {
- if (xdiff2 > ydiff2)
- {
- // increment edge 1 on Y and edge 2 on X:
- count1=ydiff1; // count for Y increment on edge 1
- count2=xdiff2; // count for X increment on edge 2
- while(count1 && count2)
- { // continue drawing until one edge is done
- // calculate edge 1:
- errorterm1+=xdiff1; // Increment error term
- if (errorterm1 >= ydiff1)
- { // if time to increment Y...
- errorterm1-=ydiff1; // ...restore error term
- offset1+=xunit1; // ...and advance offset to next pixel
- xstart1+=xunit1;
- } // end if
- count1--;
- // Calculate edge 2:
- while ((errorterm2 < xdiff2) && (count2 > 0))
- { // finished w/edge 1?
- if (count2--)
- { // count down on edge 2
- offset2+=xunit2; // increment pixel offset
- xstart2+=xunit2;
- } // end if
- errorterm2+=ydiff2; // increment error term
- if (errorterm2 < xdiff2)
- { // if not more than XDIFF
- vbuffer[offset2]=(USHORT)poly->color; // ...plot a pixel
- } // end if
- } // end while
- errorterm2-=xdiff2; // if time to increment X, restore error term
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- { // if negative...
- length=-length; // ...make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++) // from edge to edge...
- {
- vbuffer[index]=(USHORT)poly->color; // ...draw the line
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end if
- } // end if
- else
- {
- // increment edge 1 on Y and edge 2 on Y:
- count1=ydiff1; // count for Y increment on edge 1
- count2=ydiff2; // count for Y increment on edge 2
- while(count1 && count2)
- {
- // continue drawing until one edge is done
- // calculate edge 1:
- errorterm1+=xdiff1; // increment error term
- if (errorterm1 >= ydiff1)
- { // if time to increment Y
- errorterm1-=ydiff1; // ...restore error term
- offset1+=xunit1; // ...and advance offset to next pixel
- xstart1+=xunit1;
- } // end if
- count1--;
- // calculate edge 2:
- errorterm2+=xdiff2; // increment error term
- if (errorterm2 >= ydiff2)
- { // if time to increment Y
- errorterm2-=ydiff2; // ...restore error term
- offset2+=xunit2; // ...and advance offset to next pixel
- xstart2+=xunit2;
- } // end if
- --count2;
- // draw line from edge 1 to edge 2:
- length=offset2-offset1; // determine length of horizontal line
- if (length < 0)
- {
- // if negative...
- length=-length; // ...make it positive
- start=offset2; // and set START to edge 2
- } // end if
- else
- start=offset1; // else set START to edge 1
- for (int index=start; index < start+length+1; index++)
- { // from edge to edge
- vbuffer[index]=(USHORT)poly->color; // ...draw the linee
- } // end for index
- offset1+=mempitch; // advance edge 1 offset to next line
- ystart1++;
- offset2+=mempitch; // advance edge 2 offset to next line
- ystart2++;
- } // end while
- } // end else
- } // end if
- // another edge (at least) is complete. Start next edge, if any.
- if (!count1)
- { // if edge 1 is complete...
- --edgecount; // decrement the edge count
- startvert1=endvert1; // make ending vertex into start vertex
- --endvert1; // and get new ending vertex
- if (endvert1 < 0)
- endvert1=poly->num_verts-1; // check for wrap
- xend1=poly->vlist[endvert1].x+poly->x0; // get x & y of new end vertex
- yend1=poly->vlist[endvert1].y+poly->y0;
- } // end if
- if (!count2)
- { // if edge 2 is complete...
- --edgecount; // decrement the edge count
- startvert2=endvert2; // make ending vertex into start vertex
- endvert2++; // and get new ending vertex
- if (endvert2==(poly->num_verts))
- endvert2=0; // check for wrap
- xend2=poly->vlist[endvert2].x+poly->x0; // get x & y of new end vertex
- yend2=poly->vlist[endvert2].y+poly->y0;
- } // end if
- } // end while
- } // end Draw_Filled_Polygon2D16
- ///////////////////////////////////////////////////////////////
- void Build_Sin_Cos_Tables(void)
- {
- // create sin/cos lookup table
- // note the creation of one extra element; 360
- // this helps with logic in using the tables
- // generate the tables 0 - 360 inclusive
- for (int ang = 0; ang <= 360; ang++)
- {
- // convert ang to radians
- float theta = (float)ang*PI/(float)180;
- // insert next entry into table
- cos_look[ang] = cos(theta);
- sin_look[ang] = sin(theta);
- } // end for ang
- } // end Build_Sin_Cos_Tables
- //////////////////////////////////////////////////////////////
- int Translate_Polygon2D(POLYGON2D_PTR poly, int dx, int dy)
- {
- // this function translates the center of a polygon
- // test for valid pointer
- if (!poly)
- return(0);
- // translate
- poly->x0+=dx;
- poly->y0+=dy;
- // return success
- return(1);
- } // end Translate_Polygon2D
- ///////////////////////////////////////////////////////////////
- int Rotate_Polygon2D(POLYGON2D_PTR poly, int theta)
- {
- // this function rotates the local coordinates of the polygon
- // test for valid pointer
- if (!poly)
- return(0);
- // test for negative rotation angle
- if (theta < 0)
- theta+=360;
- // loop and rotate each point, very crude, no lookup!!!
- for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++)
- {
- // perform rotation
- float xr = (float)poly->vlist[curr_vert].x*cos_look[theta] -
- (float)poly->vlist[curr_vert].y*sin_look[theta];
- float yr = (float)poly->vlist[curr_vert].x*sin_look[theta] +
- (float)poly->vlist[curr_vert].y*cos_look[theta];
- // store result back
- poly->vlist[curr_vert].x = xr;
- poly->vlist[curr_vert].y = yr;
- } // end for curr_vert
- // return success
- return(1);
- } // end Rotate_Polygon2D
- ////////////////////////////////////////////////////////
- int Scale_Polygon2D(POLYGON2D_PTR poly, float sx, float sy)
- {
- // this function scalesthe local coordinates of the polygon
- // test for valid pointer
- if (!poly)
- return(0);
- // loop and scale each point
- for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++)
- {
- // scale and store result back
- poly->vlist[curr_vert].x *= sx;
- poly->vlist[curr_vert].y *= sy;
- } // end for curr_vert
- // return success
- return(1);
- } // end Scale_Polygon2D
- ///////////////////////////////////////////////////////////
- int Draw_Polygon2D16(POLYGON2D_PTR poly, UCHAR *vbuffer, int lpitch)
- {
- // this function draws a POLYGON2D based on
- // test if the polygon is visible
- if (poly->state)
- {
- // loop thru and draw a line from vertices 1 to n
- for (int index=0; index < poly->num_verts-1; index++)
- {
- // draw line from ith to ith+1 vertex
- Draw_Clip_Line16(poly->vlist[index].x+poly->x0,
- poly->vlist[index].y+poly->y0,
- poly->vlist[index+1].x+poly->x0,
- poly->vlist[index+1].y+poly->y0,
- poly->color,
- vbuffer, lpitch);
- } // end for
- // now close up polygon
- // draw line from last vertex to 0th
- Draw_Clip_Line16(poly->vlist[0].x+poly->x0,
- poly->vlist[0].y+poly->y0,
- poly->vlist[index].x+poly->x0,
- poly->vlist[index].y+poly->y0,
- poly->color,
- vbuffer, lpitch);
- // return success
- return(1);
- } // end if
- else
- return(0);
- } // end Draw_Polygon2D16
- ///////////////////////////////////////////////////////////
- int Draw_Polygon2D(POLYGON2D_PTR poly, UCHAR *vbuffer, int lpitch)
- {
- // this function draws a POLYGON2D based on
- // test if the polygon is visible
- if (poly->state)
- {
- // loop thru and draw a line from vertices 1 to n
- for (int index=0; index < poly->num_verts-1; index++)
- {
- // draw line from ith to ith+1 vertex
- Draw_Clip_Line(poly->vlist[index].x+poly->x0,
- poly->vlist[index].y+poly->y0,
- poly->vlist[index+1].x+poly->x0,
- poly->vlist[index+1].y+poly->y0,
- poly->color,
- vbuffer, lpitch);
- } // end for
- // now close up polygon
- // draw line from last vertex to 0th
- Draw_Clip_Line(poly->vlist[0].x+poly->x0,
- poly->vlist[0].y+poly->y0,
- poly->vlist[index].x+poly->x0,
- poly->vlist[index].y+poly->y0,
- poly->color,
- vbuffer, lpitch);
- // return success
- return(1);
- } // end if
- else
- return(0);
- } // end Draw_Polygon2D
- ///////////////////////////////////////////////////////////////
- // these are the matrix versions, note they are more inefficient for
- // single transforms, but their power comes into play when you concatenate
- // multiple transformations, not to mention that all transforms are accomplished
- // with the same code, just the matrix differs
- int Translate_Polygon2D_Mat(POLYGON2D_PTR poly, int dx, int dy)
- {
- // this function translates the center of a polygon by using a matrix multiply
- // on the the center point, this is incredibly inefficient, but for educational purposes
- // if we had an object that wasn't in local coordinates then it would make more sense to
- // use a matrix, but since the origin of the object is at x0,y0 then 2 lines of code can
- // translate, but lets do it the hard way just to see :)
- // test for valid pointer
- if (!poly)
- return(0);
- MATRIX3X2 mt; // used to hold translation transform matrix
- // initialize the matrix with translation values dx dy
- Mat_Init_3X2(&mt,1,0, 0,1, dx, dy);
- // create a 1x2 matrix to do the transform
- MATRIX1X2 p0 = {poly->x0, poly->y0};
- MATRIX1X2 p1 = {0,0}; // this will hold result
- // now translate via a matrix multiply
- Mat_Mul_1X2_3X2(&p0, &mt, &p1);
- // now copy the result back into polygon
- poly->x0 = p1.M[0];
- poly->y0 = p1.M[1];
- // return success
- return(1);
- } // end Translate_Polygon2D_Mat
- ///////////////////////////////////////////////////////////////
- int Rotate_Polygon2D_Mat(POLYGON2D_PTR poly, int theta)
- {
- // this function rotates the local coordinates of the polygon
- // test for valid pointer
- if (!poly)
- return(0);
- // test for negative rotation angle
- if (theta < 0)
- theta+=360;
- MATRIX3X2 mr; // used to hold rotation transform matrix
- // initialize the matrix with translation values dx dy
- Mat_Init_3X2(&mr,cos_look[theta],sin_look[theta],
- -sin_look[theta],cos_look[theta],
- 0, 0);
- // loop and rotate each point, very crude, no lookup!!!
- for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++)
- {
- // create a 1x2 matrix to do the transform
- MATRIX1X2 p0 = {poly->vlist[curr_vert].x, poly->vlist[curr_vert].y};
- MATRIX1X2 p1 = {0,0}; // this will hold result
- // now rotate via a matrix multiply
- Mat_Mul_1X2_3X2(&p0, &mr, &p1);
- // now copy the result back into vertex
- poly->vlist[curr_vert].x = p1.M[0];
- poly->vlist[curr_vert].y = p1.M[1];
- } // end for curr_vert
- // return success
- return(1);
- } // end Rotate_Polygon2D_Mat
- ////////////////////////////////////////////////////////
- int Scale_Polygon2D_Mat(POLYGON2D_PTR poly, float sx, float sy)
- {
- // this function scalesthe local coordinates of the polygon
- // test for valid pointer
- if (!poly)
- return(0);
- MATRIX3X2 ms; // used to hold scaling transform matrix
- // initialize the matrix with translation values dx dy
- Mat_Init_3X2(&ms,sx,0,
- 0,sy,
- 0, 0);
- // loop and scale each point
- for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++)
- {
- // scale and store result back
- // create a 1x2 matrix to do the transform
- MATRIX1X2 p0 = {poly->vlist[curr_vert].x, poly->vlist[curr_vert].y};
- MATRIX1X2 p1 = {0,0}; // this will hold result
- // now scale via a matrix multiply
- Mat_Mul_1X2_3X2(&p0, &ms, &p1);
- // now copy the result back into vertex
- poly->vlist[curr_vert].x = p1.M[0];
- poly->vlist[curr_vert].y = p1.M[1];
- } // end for curr_vert
- // return success
- return(1);
- } // end Scale_Polygon2D_Mat
- ///////////////////////////////////////////////////////////
- int Mat_Mul_3X3(MATRIX3X3_PTR ma,
- MATRIX3X3_PTR mb,
- MATRIX3X3_PTR mprod)
- {
- // this function multiplies two matrices together and
- // and stores the result
- for (int row=0; row<3; row++)
- {
- for (int col=0; col<3; col++)
- {
- // compute dot product from row of ma
- // and column of mb
- float sum = 0; // used to hold result
- for (int index=0; index<3; index++)
- {
- // add in next product pair
- sum+=(ma->M[row][index]*mb->M[index][col]);
- } // end for index
- // insert resulting row,col element
- mprod->M[row][col] = sum;
- } // end for col
- } // end for row
- return(1);
- } // end Mat_Mul_3X3
- ////////////////////////////////////////////////////////////////
- int Mat_Mul_1X3_3X3(MATRIX1X3_PTR ma,
- MATRIX3X3_PTR mb,
- MATRIX1X3_PTR mprod)
- {
- // this function multiplies a 1x3 matrix against a
- // 3x3 matrix - ma*mb and stores the result
- for (int col=0; col<3; col++)
- {
- // compute dot product from row of ma
- // and column of mb
- float sum = 0; // used to hold result
- for (int index=0; index<3; index++)
- {
- // add in next product pair
- sum+=(ma->M[index]*mb->M[index][col]);
- } // end for index
- // insert resulting col element
- mprod->M[col] = sum;
- } // end for col
- return(1);
- } // end Mat_Mul_1X3_3X3
- ////////////////////////////////////////////////////////////////
- int Mat_Mul_1X2_3X2(MATRIX1X2_PTR ma,
- MATRIX3X2_PTR mb,
- MATRIX1X2_PTR mprod)
- {
- // this function multiplies a 1x2 matrix against a
- // 3x2 matrix - ma*mb and stores the result
- // using a dummy element for the 3rd element of the 1x2
- // to make the matrix multiply valid i.e. 1x3 X 3x2
- for (int col=0; col<2; col++)
- {
- // compute dot product from row of ma
- // and column of mb
- float sum = 0; // used to hold result
- for (int index=0; index<2; index++)
- {
- // add in next product pair
- sum+=(ma->M[index]*mb->M[index][col]);
- } // end for index
- // add in last element * 1
- sum+= mb->M[index][col];
- // insert resulting col element
- mprod->M[col] = sum;
- } // end for col
- return(1);
- } // end Mat_Mul_1X2_3X2
- //////////////////////////////////////////////////////////////
- #if 0
- inline int Mat_Init_3X2(MATRIX3X2_PTR ma,
- float m00, float m01,
- float m10, float m11,
- float m20, float m21)
- {
- // this function fills a 3x2 matrix with the sent data in row major form
- ma->M[0][0] = m00; ma->M[0][1] = m01;
- ma->M[1][0] = m10; ma->M[1][1] = m11;
- ma->M[2][0] = m20; ma->M[2][1] = m21;
- // return success
- return(1);
- } // end Mat_Init_3X2
- #endif
- /////////////////////////////////////////////////////////////////