Exemplo n.º 1
0
//
// DrawDib uses StretchDIBits to display the bitmap.
void CDIBitmap :: DrawDIB( CDC* pDC, int x, int y, int width, int height ) {
    ASSERT( pDC );
    HDC     hdc = pDC->GetSafeHdc();

	CPalette * pOldPal = 0;

	if( m_pPal ) {
		pOldPal = pDC->SelectPalette( m_pPal, FALSE );
		pDC->RealizePalette();
		// Make sure to use the stretching mode best for color pictures
		pDC->SetStretchBltMode(COLORONCOLOR);
	}

    if( m_pInfo )
        StretchDIBits( hdc,
                       x,
                       y,
                       width,
                       height,
                       0,
                       0,
                       GetWidth(),
                       GetHeight(),
                       GetPixelPtr(),
                       GetHeaderPtr(),
                       DIB_RGB_COLORS,
                       SRCCOPY );
	
	if( m_pPal )
		pDC->SelectPalette( pOldPal, FALSE );
}
Exemplo n.º 2
0
static inline
void DrawTriangle2(const Vertex& v1, const Vertex& v2, const Vertex& v3)
{
	float y1 = v1.y;
	float y2 = v2.y;
	float y3 = v3.y;

	float x1 = v1.x;
	float x2 = v2.x;
	float x3 = v3.x;

	// Deltas
	float Dx12 = x1 - x2;
	float Dx23 = x2 - x3;
	float Dx31 = x3 - x1;

	float Dy12 = y1 - y2;
	float Dy23 = y2 - y3;
	float Dy31 = y3 - y1;

	// Bounding rectangle
	int minx = (int)min(x1, x2, x3);
	int maxx = (int)max(x1, x2, x3);
	int miny = (int)min(y1, y2, y3);
	int maxy = (int)max(y1, y2, y3);

	pixel_t* colorBuffer = GetPixelPtr(0, miny);

	// Constant part of half-edge functions
	float C1 = Dy12 * x1 - Dx12 * y1;
	float C2 = Dy23 * x2 - Dx23 * y2;
	float C3 = Dy31 * x3 - Dx31 * y3;

	float Cy1 = C1 + Dx12 * miny - Dy12 * minx;
	float Cy2 = C2 + Dx23 * miny - Dy23 * minx;
	float Cy3 = C3 + Dx31 * miny - Dy31 * minx;

	// Scan through bounding rectangle
	for (int y = miny; y < maxy; y++) {
		// Start value for horizontal scan
		float Cx1 = Cy1;
		float Cx2 = Cy2;
		float Cx3 = Cy3;
		for (int x = minx; x < maxx; x++) {
			if (Cx1 > 0 && Cx2 > 0 && Cx3 > 0) {
				colorBuffer[x] = 0x00FFFFFF;	// White
			}
			Cx1 -= Dy12;
			Cx2 -= Dy23;
			Cx3 -= Dy31;
		}
		Cy1 += Dx12;
		Cy2 += Dx23;
		Cy3 += Dx31;
		OffsetPtr(colorBuffer, GetLineOffset());
	}
	
}
Exemplo n.º 3
0
			///
			/// LDR I/O, only available to LDR images
			void SavePng(const std::string& file_name)
			{
				BOOST_STATIC_ASSERT( (boost::is_same<T, UCHAR>::value) );
				BOOST_STATIC_ASSERT( channel == 3 );

				size_t pos = file_name.find_last_of(".");
				std::string file_type = file_name.substr(++pos, std::string::npos);
				boost::to_lower(file_type);
				assert(file_type == "png");

				FILE* fp;
				if((fp = fopen(file_name.c_str(), "wb")) == NULL)
					assert(0);

				png_structp _png_ptr;
				png_infop _info_ptr;
			    
				_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
				if(!_png_ptr)
					assert(0);

				_info_ptr = png_create_info_struct(_png_ptr);
				if (!_info_ptr) 
				{
					png_destroy_write_struct(&_png_ptr, png_infopp_NULL);
					assert(0);
				}

				if (setjmp(png_jmpbuf(_png_ptr))) 
				{
					png_destroy_write_struct(&_png_ptr, &_info_ptr);
					assert(0);
				}
			    
				png_init_io(_png_ptr, fp);
					
				png_set_IHDR(_png_ptr, _info_ptr, GetWidth(), GetHeight(), 8,
								 PNG_COLOR_TYPE_RGB,
								 PNG_INTERLACE_NONE,
								 PNG_COMPRESSION_TYPE_DEFAULT,
								 PNG_FILTER_TYPE_DEFAULT);
			    
				png_write_info(_png_ptr, _info_ptr);

				if (little_endian() && false /* RGB depth always = 8 */)
					png_set_swap(_png_ptr);
			    
				for(UINT y = 0; y < GetHeight(); ++y) 
					png_write_row(_png_ptr, (png_bytep)GetPixelPtr(0, y));

				png_write_end(_png_ptr,_info_ptr);
				fclose(fp);
			}
Exemplo n.º 4
0
int CDIBitmap :: DrawDIB( CDC * pDC, CRect & rectDC, CRect & rectDIB ) {
    ASSERT( pDC );
    HDC     hdc = pDC->GetSafeHdc();

	CPalette * pOldPal = 0;

	if( m_pPal ) {
		pOldPal = pDC->SelectPalette( m_pPal, FALSE );
		pDC->RealizePalette();
		// Make sure to use the stretching mode best for color pictures
		pDC->SetStretchBltMode(COLORONCOLOR);
	}

	int nRet = 0;

    if( m_pInfo )
		nRet =	SetDIBitsToDevice(
					hdc,					// device
					rectDC.left,			// DestX
					rectDC.top,				// DestY
					rectDC.Width(),			// DestWidth
					rectDC.Height(),		// DestHeight
					rectDIB.left,			// SrcX
					GetHeight() -
						rectDIB.top -
						rectDIB.Height(),	// SrcY
					0,						// StartScan
					GetHeight(),			// NumScans
					GetPixelPtr(),			// color data
					GetHeaderPtr(),			// header data
					DIB_RGB_COLORS			// color usage
				);
	
	if( m_pPal )
		pDC->SelectPalette( pOldPal, FALSE );

	return nRet;
}
Exemplo n.º 5
0
			///
			/// Normalize HDR for conversion to LDR
			void Normalize()
			{
				//only for HDR
				BOOST_STATIC_ASSERT( (boost::is_same<T, float>::value) );
				BOOST_STATIC_ASSERT( channel == 3 );

				float max = 0;

				for(int y = 0; y < GetHeight(); y++)
					for(int x = 0; x < GetWidth(); x++)
					{
						std::max = max(max, GetPixelPtr(x, y)[0]);
						std::max = max(max, GetPixelPtr(x, y)[1]);
						std::max = max(max, GetPixelPtr(x, y)[2]);
					}
				
				for(int y = 0; y < GetHeight(); y++)
					for(int x = 0; x < GetWidth(); x++)
					{
						 GetPixelPtr(x, y)[0] /= max;
						 GetPixelPtr(x, y)[1] /= max;
						 GetPixelPtr(x, y)[2] /= max;
					}
			}
Exemplo n.º 6
0
			///
			/// LDR I/O, only available to LDR images
			void LoadPng(const std::string& file_name)
			{
				BOOST_STATIC_ASSERT( (boost::is_same<T, UCHAR>::value) );
				BOOST_STATIC_ASSERT( channel == 3 );

				size_t pos = file_name.find_last_of(".");
				std::string file_type = file_name.substr(++pos, std::string::npos);
				boost::to_lower(file_type);
				assert(file_type == "png");

				FILE* fp = 0;
				fp = fopen(file_name.c_str(), "rb");
				if(fp == 0) 
				{
					assert(0);
					return;
				}
						
				char buf[PNG_BYTES_TO_CHECK];
				png_structp _png_ptr;
				png_infop _info_ptr;

				// read in some of the signature bytes
				if(fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK)
					assert(0);

				// compare the first PNG_BYTES_TO_CHECK bytes of the signature.
				if(png_sig_cmp((png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0)
					assert(0);

				_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
				if(_png_ptr == NULL)
					assert(0);

				// allocate/initialize the image information data
				_info_ptr = png_create_info_struct(_png_ptr);
				if (_info_ptr == NULL) 
				{
					png_destroy_read_struct(&_png_ptr,png_infopp_NULL,png_infopp_NULL);
					assert(0);
				}

				if (setjmp(png_jmpbuf(_png_ptr))) 
				{
					//free all of the memory associated with the png_ptr and info_ptr
					png_destroy_read_struct(&_png_ptr, &_info_ptr, png_infopp_NULL);
					assert(0);
				}

				png_init_io(_png_ptr, fp);
				png_set_sig_bytes(_png_ptr, PNG_BYTES_TO_CHECK);
				png_read_info(_png_ptr, _info_ptr);

				if (little_endian() && png_get_bit_depth(_png_ptr,_info_ptr)>8)
					png_set_swap(_png_ptr);
						
				SetSize((png_get_image_width(_png_ptr,_info_ptr)), (png_get_image_height(_png_ptr,_info_ptr)));
												  
				png_uint_32 width, height;
				int bit_depth, color_type, interlace_type;

				png_get_IHDR(_png_ptr, _info_ptr, &width, &height,&bit_depth,&color_type,&interlace_type, int_p_NULL, int_p_NULL);
			    
				for(png_uint_32 y = 0; y < height; ++y) 
					png_read_row(_png_ptr,(png_bytep)GetPixelPtr(0, y), NULL);

				png_read_end(_png_ptr,NULL);
				fclose(fp);
			}
Exemplo n.º 7
0
// See the header file for a full description of how this function
// behaves.
void CompositeBitmap(CSBitmap* Bottom, CSBitmap* Top, int StartX, int StartY, uint8_t GlobalOpacity /* = 255*/)
{
	// Insert your code here.


	//Check to see if the Top bitmap is not visible at all, if it's true, then just quit
	if((StartX >= GetWidth(Bottom))
		|| (StartY >= GetHeight(Bottom)))
		return;

	int indexX = StartX, indexY = StartY; //the starting index from the image bits
	int EndX = StartX + GetWidth(Top); //the ending index
	int EndY = StartY + GetHeight(Top);

	//adjust the starting image index if the location is off the edge
	if(StartX < 0)
		StartX = 0;
	if(StartY < 0)
		StartY = 0;

	//check to see again if the Top bitmap is not visible at all
	if((EndX < 0)
		|| (EndY < 0))
		return;
	
	//adjust the starting image index if the location is off the edge
	if(EndX > GetWidth(Bottom))
		EndX = GetWidth(Bottom);
	if(EndY > GetHeight(Bottom))
		EndY = GetHeight(Bottom);


	uint8_t *TopBit, *BottomBit;
	uint8_t alpha;

	//get this only if we have 8-bit Top
	RGBQUAD palette[255] = {0}; 
	if(GetChannels(Top) == 1)
		GetPalette(Top, 0, 256, palette);

	switch(GetChannels(Top))
	{
	case 4: //32
		for(int Ty = StartY; Ty < EndY; Ty++)
		{
			TopBit = GetPixelPtr(Top, StartX - indexX, Ty - indexY);
			BottomBit = GetPixelPtr(Bottom, StartX, Ty);

			for(int Tx = StartX; Tx < EndX; Tx++)
			{
				alpha = TopBit[ALPHA_BITMAP_OFFSET];
				alpha = (alpha * GlobalOpacity + 127) / 255;
				
				if(alpha == 255)
				{
					//use memcpy next time...might be faster
					BottomBit[RED_BITMAP_OFFSET] = TopBit[RED_BITMAP_OFFSET];
					BottomBit[GREEN_BITMAP_OFFSET] = TopBit[GREEN_BITMAP_OFFSET];
					BottomBit[BLUE_BITMAP_OFFSET] = TopBit[BLUE_BITMAP_OFFSET];
				}
				else if(alpha > 0)
				{
					BottomBit[RED_BITMAP_OFFSET] = BottomBit[RED_BITMAP_OFFSET] + ((TopBit[RED_BITMAP_OFFSET] - BottomBit[RED_BITMAP_OFFSET]) * alpha + 127) / 255;
					BottomBit[GREEN_BITMAP_OFFSET] = BottomBit[GREEN_BITMAP_OFFSET] + ((TopBit[GREEN_BITMAP_OFFSET] - BottomBit[GREEN_BITMAP_OFFSET]) * alpha + 127) / 255;
					BottomBit[BLUE_BITMAP_OFFSET] = BottomBit[BLUE_BITMAP_OFFSET] + ((TopBit[BLUE_BITMAP_OFFSET] - BottomBit[BLUE_BITMAP_OFFSET]) * alpha + 127) / 255;
				}
				TopBit += GetChannels(Top);
				BottomBit += GetChannels(Bottom);
			}
		}
		break;
	case 3: //24
		//since 24-bit don't have Alpha, just use the global opacity
		for(int Ty = StartY; Ty < EndY; Ty++)
		{
			TopBit = GetPixelPtr(Top, StartX - indexX, Ty - indexY);
			BottomBit = GetPixelPtr(Bottom, StartX, Ty);

			for(int Tx = StartX; Tx < EndX; Tx++)
			{	
				if(GlobalOpacity == 255)
				{
					//use memcpy next time...might be faster
					BottomBit[RED_BITMAP_OFFSET] = TopBit[RED_BITMAP_OFFSET];
					BottomBit[GREEN_BITMAP_OFFSET] = TopBit[GREEN_BITMAP_OFFSET];
					BottomBit[BLUE_BITMAP_OFFSET] = TopBit[BLUE_BITMAP_OFFSET];
				}
				else if(GlobalOpacity > 0)
				{
					BottomBit[RED_BITMAP_OFFSET] = BottomBit[RED_BITMAP_OFFSET] + ((TopBit[RED_BITMAP_OFFSET] - BottomBit[RED_BITMAP_OFFSET]) * GlobalOpacity + 127) / 255;
					BottomBit[GREEN_BITMAP_OFFSET] = BottomBit[GREEN_BITMAP_OFFSET] + ((TopBit[GREEN_BITMAP_OFFSET] - BottomBit[GREEN_BITMAP_OFFSET]) * GlobalOpacity + 127) / 255;
					BottomBit[BLUE_BITMAP_OFFSET] = BottomBit[BLUE_BITMAP_OFFSET] + ((TopBit[BLUE_BITMAP_OFFSET] - BottomBit[BLUE_BITMAP_OFFSET]) * GlobalOpacity + 127) / 255;
				}
				TopBit += GetChannels(Top);
				BottomBit += GetChannels(Bottom);
			}
		}
		break;
	case 2: //16
		//arg
		break;
	case 1: //8
		for(int Ty = StartY; Ty < EndY; Ty++)
		{
			TopBit = GetPixelPtr(Top, StartX - indexX, Ty - indexY);
			BottomBit = GetPixelPtr(Bottom, StartX, Ty);

			for(int Tx = StartX; Tx < EndX; Tx++)
			{	
				if(GlobalOpacity == 255)
				{
					BottomBit[RED_BITMAP_OFFSET] = palette[*TopBit].rgbRed;
					BottomBit[GREEN_BITMAP_OFFSET] = palette[*TopBit].rgbGreen;
					BottomBit[BLUE_BITMAP_OFFSET] = palette[*TopBit].rgbBlue;
				}
				else if(GlobalOpacity > 0 && GlobalOpacity < 255)
				{
					BottomBit[RED_BITMAP_OFFSET] = BottomBit[RED_BITMAP_OFFSET] + ((palette[*TopBit].rgbRed - BottomBit[RED_BITMAP_OFFSET]) * GlobalOpacity + 127) / 255;
					BottomBit[GREEN_BITMAP_OFFSET] = BottomBit[GREEN_BITMAP_OFFSET] + ((palette[*TopBit].rgbGreen - BottomBit[GREEN_BITMAP_OFFSET]) * GlobalOpacity + 127) / 255;
					BottomBit[BLUE_BITMAP_OFFSET] = BottomBit[BLUE_BITMAP_OFFSET] + ((palette[*TopBit].rgbBlue - BottomBit[BLUE_BITMAP_OFFSET]) * GlobalOpacity + 127) / 255;
				}

				TopBit += GetChannels(Top);
				BottomBit += GetChannels(Bottom);
			}
		}
		break;
	}
}
Exemplo n.º 8
0
void DrawTriangle5(const Vertex& v1, const Vertex& v2, const Vertex& v3)
{
	// 28.4 fixed-point coordinates
	const int Y1 = iround(16.0f * v1.y);
	const int Y2 = iround(16.0f * v2.y);
	const int Y3 = iround(16.0f * v3.y);

	const int X1 = iround(16.0f * v1.x);
	const int X2 = iround(16.0f * v2.x);
	const int X3 = iround(16.0f * v3.x);
	// Deltas
/*
  This was really easy. I fit 6 words into XMMs and could do all the
  subtraction and shifting.
*/
	const int DX12 = X1 - X2;
	const int DX23 = X2 - X3;
	const int DX31 = X3 - X1;

	const int DY12 = Y1 - Y2;
	const int DY23 = Y2 - Y3;
	const int DY31 = Y3 - Y1;

	// Fixed-point deltas
	const int FDX12 = DX12 << 4;
	const int FDX23 = DX23 << 4;
	const int FDX31 = DX31 << 4;
	const int FDY12 = DY12 << 4;
	const int FDY23 = DY23 << 4;
	const int FDY31 = DY31 << 4;

	// Bounding rectangle
/*
  These four went in 2 clock cycles :)
*/
	int minx = (min(X1, X2, X3) + 0xF) >> 4;
	int maxx = (max(X1, X2, X3) + 0xF) >> 4;
	int miny = (min(Y1, Y2, Y3) + 0xF) >> 4;
	int maxy = (max(Y1, Y2, Y3) + 0xF) >> 4;

	// Block size, standard 8x8 (must be power of two)
	const int q = 8;
/*
  I found out this to be very interesting dynamically. There were situations
  where 4 or 16 was better. Imagine triangles from 4x4px bounding in size
  upto 500x500 in size...
*/
	// Start in corner of 8x8 block
	minx &= ~(q - 1); // This and later is all in 64-bit x86 ASM without SSE
	miny &= ~(q - 1);

	pixel_t* colorBuffer = GetPixelPtr(0, miny);
	// Half-edge constants
	int C1 = DY12 * X1 - DX12 * Y1; // SSE only has instructions for WORDs
	int C2 = DY23 * X2 - DX23 * Y2; // but this needs at least DWORDs and
	int C3 = DY31 * X3 - DX31 * Y3; // doing 6 multiplys with IMUL is faster
	// than converting it to SSE and doing 2*3 MULUDQs with additional sign-
	// checking because UDQ is UNsigned :(

	// Correct for fill convention
	if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
	if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
	if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
	// Loop through blocks
	for(int y = miny; y < maxy; y += q)
	{
		for(int x = minx; x < maxx; x += q)
		{
			// Corners of block
			int x0 = x << 4;
			int x1 = (x + q - 1) << 4;
			int y0 = y << 4;
			int y1 = (y + q - 1) << 4;

			// Evaluate half-space functions
/*
  This one here is very painful and even in case of a right triangle sitting in
  one half of the bounding box it takes 24 IMULs for every 8x8 pixel region
  empty or not. One or two optimizations are possible, though. You cast these
  bools to ints here, but actually you could just add these results without
  shifting (a00+a10+a01+a11) because you only check whether its all 0 or
  all 1. Then it becomes 0 or 4. Only loss is that you don't know which ones
  where 1 and which ones 0 (may be necessary with masking). The definite
  one optimization is that you don't have to wait until c to check for 0, but
  you can to it after every four bools. Bail out of the loop quickly after a==0
  so you will cut off these painful 16 IMULs, 16 ADDs/SUBs, 8 CMPs, 4 SHLs
  and 4 ORs. That on average will improve throughput by 10-35% depending
  on the triangles.
*/
			bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
			bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
			bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
			bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
			int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
	
			bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
			bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
			bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
			bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
			int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
	
			bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
			bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
			bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
			bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
			int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);

			// Skip block when outside an edge
/*
  This one can be cleverly done with
  #define has_nullbyte_(x) ((x - 0x01010101) & ~x & 0x80808080)
  hint: search for "null" at
  http://www.azillionmonkeys.com/qed/asmexample.html
  but I didn't need it at all because of the optimizations above
*/
			if(a == 0x0 || b == 0x0 || c == 0x0) continue;
			pixel_t* buffer = colorBuffer;

			// Accept whole block when totally covered
/*
  By fusing a,b,c together earlier I could make here only one test which is
  if(c==0xFFF) - that is when c=a<<8|b<<4|c
*/
			if(a == 0xF && b == 0xF && c == 0xF)
			{
				for(int iy = 0; iy < q; iy++)
				{
					for(int ix = x; ix < x + q; ix++)
					{
						buffer[ix] = 0x00007F00; // Green
/*
  This part here gave a really good boost. I switched to SSE for a second
  here and shuffled the color to all parts of the 128-bit register. It could
  write 16 bytes per clock and with some macro magic, I made it calculate
  from the q how much of these it needed. The inner loop is too tight to use
  it at all so I left it out :)
*/
					}
					OffsetPtr(buffer, GetLineOffset());
				}
			}
			else // Partially covered block
			{
				int CY1 = C1 + DX12 * y0 - DY12 * x0;
				int CY2 = C2 + DX23 * y0 - DY23 * x0;
				int CY3 = C3 + DX31 * y0 - DY31 * x0;

				for(int iy = y; iy < y + q; iy++)
				{
					int CX1 = CY1;
					int CX2 = CY2;
					int CX3 = CY3;

					for(int ix = x; ix < x + q; ix++)
					{
						if(CX1 > 0 && CX2 > 0 && CX3 > 0)
						{
							buffer[ix] = 0x0000007F; // Blue
						}

						CX1 -= FDY12;
						CX2 -= FDY23;
						CX3 -= FDY31;
					}

					CY1 += FDX12;
					CY2 += FDX23;
					CY3 += FDX31;
					OffsetPtr(buffer, GetLineOffset());
				}
			}
		}
		OffsetPtr(colorBuffer, q * GetLineOffset());
	}

}
Exemplo n.º 9
0
void DrawTriangle4(const Vertex& v1, const Vertex& v2, const Vertex& v3)
{
	// 28.4 fixed-point coordinates
	const int Y1 = iround(16.0f * v1.y);
	const int Y2 = iround(16.0f * v2.y);
	const int Y3 = iround(16.0f * v3.y);
	const int X1 = iround(16.0f * v1.x);
	const int X2 = iround(16.0f * v2.x);
	const int X3 = iround(16.0f * v3.x);
	// Deltas
	const int DX12 = X1 - X2;
	const int DX23 = X2 - X3;
	const int DX31 = X3 - X1;
	const int DY12 = Y1 - Y2;
	const int DY23 = Y2 - Y3;
	const int DY31 = Y3 - Y1;
	// Fixed-point deltas
	const int FDX12 = DX12 << 4;
	const int FDX23 = DX23 << 4;
	const int FDX31 = DX31 << 4;
	const int FDY12 = DY12 << 4;
	const int FDY23 = DY23 << 4;
	const int FDY31 = DY31 << 4;
	// Bounding rectangle
	int minx = (min(X1, X2, X3) + 0xF) >> 4;
	int maxx = (max(X1, X2, X3) + 0xF) >> 4;
	int miny = (min(Y1, Y2, Y3) + 0xF) >> 4;
	int maxy = (max(Y1, Y2, Y3) + 0xF) >> 4;
	// Block size, standard 8x8 (must be power of two)
	const int q = 8;
	// Start in corner of 8x8 block
	minx &= ~(q - 1);
	miny &= ~(q - 1);
	pixel_t* colorBuffer = GetPixelPtr(0, miny);
	// Half-edge constants
	int C1 = DY12 * X1 - DX12 * Y1;
	int C2 = DY23 * X2 - DX23 * Y2;
	int C3 = DY31 * X3 - DX31 * Y3;
	// Correct for fill convention
	if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
	if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
	if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
	// Loop through blocks
	for (int y = miny; y < maxy; y += q) {
		for (int x = minx; x < maxx; x += q) {
			// Corners of block
			int x0 = x << 4;
			int x1 = (x + q - 1) << 4;
			int y0 = y << 4;
			int y1 = (y + q - 1) << 4;
			// Evaluate half-space functions
			bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
			bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
			bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
			bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
			int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
			bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
			bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
			bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
			bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
			int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
			bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
			bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
			bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
			bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
			int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
			// Skip block when outside an edge
			if (a == 0x0 || b == 0x0 || c == 0x0) continue;
			pixel_t* buffer = colorBuffer;
			// Accept whole block when totally covered
			if (a == 0xF && b == 0xF && c == 0xF) {
				for (int iy = 0; iy < q; iy++) {
					for (int ix = x; ix < x + q; ix++) {
						buffer[ix] = 0x00007F00; // Green
					}
					OffsetPtr(buffer, GetLineOffset());
				}
			}else {// Partially covered block
				int CY1 = C1 + DX12 * y0 - DY12 * x0;
				int CY2 = C2 + DX23 * y0 - DY23 * x0;
				int CY3 = C3 + DX31 * y0 - DY31 * x0;
				for (int iy = y; iy < y + q; iy++) {
					int CX1 = CY1;
					int CX2 = CY2;
					int CX3 = CY3;
					for (int ix = x; ix < x + q; ix++) {
						if (CX1 > 0 && CX2 > 0 && CX3 > 0) {
							buffer[ix] = 0x0000007F; // Blue
						}
						CX1 -= FDY12;
						CX2 -= FDY23;
						CX3 -= FDY31;
					}
					CY1 += FDX12;
					CY2 += FDX23;
					CY3 += FDX31;
					OffsetPtr(buffer, GetLineOffset());
				}
			}
		}
		OffsetPtr(colorBuffer, q*GetLineOffset());
	}
}
Exemplo n.º 10
0
void DrawTriangle3(const Vertex& v1, const Vertex& v2, const Vertex& v3)
{
	// 28.4 fixed-point coordinates
	const int Y1 = iround(16.0f * v1.y);
	const int Y2 = iround(16.0f * v2.y);
	const int Y3 = iround(16.0f * v3.y);

	const int X1 = iround(16.0f * v1.x);
	const int X2 = iround(16.0f * v2.x);
	const int X3 = iround(16.0f * v3.x);

	// Deltas
	const int DX12 = X1 - X2;
	const int DX23 = X2 - X3;
	const int DX31 = X3 - X1;

	const int DY12 = Y1 - Y2;
	const int DY23 = Y2 - Y3;
	const int DY31 = Y3 - Y1;

	// Fixed-point deltas
	const int FDX12 = DX12 << 4;
	const int FDX23 = DX23 << 4;
	const int FDX31 = DX31 << 4;

	const int FDY12 = DY12 << 4;
	const int FDY23 = DY23 << 4;
	const int FDY31 = DY31 << 4;

	// Bounding rectangle
	int minx = (min(X1, X2, X3) + 0xF) >> 4;
	int maxx = (max(X1, X2, X3) + 0xF) >> 4;
	int miny = (min(Y1, Y2, Y3) + 0xF) >> 4;
	int maxy = (max(Y1, Y2, Y3) + 0xF) >> 4;

	pixel_t* colorBuffer = GetPixelPtr(0, miny);

	// Half-edge constants
	int C1 = DY12 * X1 - DX12 * Y1;
	int C2 = DY23 * X2 - DX23 * Y2;
	int C3 = DY31 * X3 - DX31 * Y3;

	// Correct for fill convention
	if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
	if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
	if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;

	int CY1 = C1 + DX12 * (miny << 4) - DY12 * (minx << 4);
	int CY2 = C2 + DX23 * (miny << 4) - DY23 * (minx << 4);
	int CY3 = C3 + DX31 * (miny << 4) - DY31 * (minx << 4);

	for (int y = miny; y < maxy; y++) {
		int CX1 = CY1;
		int CX2 = CY2;
		int CX3 = CY3;
		for (int x = minx; x < maxx; x++) {
			if (CX1 > 0 && CX2 > 0 && CX3 > 0) {
				colorBuffer[x] = 0x00FFFFFF;
			}
			CX1 -= FDY12;
			CX2 -= FDY23;
			CX3 -= FDY31;
		}
		CY1 += FDX12;
		CY2 += FDX23;
		CY3 += FDX31;
		OffsetPtr(colorBuffer, GetLineOffset());
	}
	
}