← index
PSP.Homebrew/apps/SDL3D/mxpixelbuffer.h
Source: PSP.Homebrew/apps/SDL3D/mxpixelbuffer.h
#include <SDL.h>



extern SDL_Surface *front;
extern void *buf;
int max_clip_x = 0, max_clip_y = 0, min_clip_x = 0, min_clip_y = 0;
#define D3DCOLOR unsigned long




inline unsigned long D3DCOLOR_XRGB(unsigned char r, unsigned char g, unsigned char b) {
	return SDL_MapRGB(front->format, r, g, b);
}

void setpixel(void *buf, Uint32 x, Uint32 y, Uint32 color, Uint8 type, Uint16 pitch) ;

inline void fast_sp(int x, int y, unsigned long color) {
	setpixel(buf,int(x),int(y),color,front->format->BitsPerPixel,front->pitch);
}


inline void Swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

inline void Swap(float& a, float& b)
{
	float temp = a;
	a = b;
	b = temp;
}

void *lock(SDL_Surface *surf, Uint8 type) {
	if(SDL_MUSTLOCK(surf)) {
		if(SDL_LockSurface(surf) < 0)
			return 0;
	}

	type = surf->format->BitsPerPixel;

	switch(surf->format->BitsPerPixel) {
		case 1:
		case 8:
			return (Uint8*)surf->pixels;
			break;
		case 16:
		case 2:
			return (Uint16*)surf->pixels;
			break;
		case 24:
		case 3:
			return (Uint32*)surf->pixels;
			break;
		case 32:
		case 4:
			return (Uint32*)surf->pixels;
			break;
		default:
			break;
	}

	return 0;

}



void unlock(SDL_Surface *surf) {
	if(SDL_MUSTLOCK(surf)) {
		SDL_UnlockSurface(surf);
	}
}

void setpixel(void *buff, Uint32 x, Uint32 y, Uint32 color, Uint8 type, Uint16 pitch) {
	static Uint8 *ubuff8 = 0;

	if(!(x >= 0 && x < front->w && y >= 0 && y < front->h))
		return;

	switch(type) {
		case 1:
		case 8:
			{ 
				Uint8 *buf = (Uint8*)buff;
				buf += (y * pitch) + x;
				*buf = (Uint8) color;

			}
			break;
		case 2:
		case 16:
			{
				static Uint16 *ubuff16 = 0;
				ubuff8 = (Uint8*) buff;
				ubuff8 += (y * pitch) + (x*2);
				
				ubuff16 = (Uint16*) ubuff8;
				*ubuff16 = (Uint16) color;
			}
			break;
		case 3:
		case 24:
			{
				static char c1 = 0,c2 = 0,c3 = 0;

				ubuff8 = (Uint8*) buff;
				ubuff8 += (y * pitch) + (x*3);
				if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
					c1 = (color & 0xFF0000) >> 16;
					c2 = (color & 0x00FF00) >> 8;
					c3 = (color & 0x0000FF);
				} else {
					c3 = (color & 0xFF0000) >> 16;
					c2 = (color & 0x00FF00) >> 8;
					c1 = (color & 0x0000FF);
				}
				ubuff8[0] = c3;
				ubuff8[1] = c2;
				ubuff8[2] = c1;
			}
			break;
		case 4:
		case 32:
			{
			static Uint32 *ubuff32 = 0;
			ubuff8 = (Uint8*) buff;
			ubuff8 += (y*pitch) + (x*4);
			ubuff32 = (Uint32*)ubuff8;
			*ubuff32 = color;
			}
			break;
	}

}

void drawhline(int x,int x2, int y, D3DCOLOR color) {
	for(int p = x; p <= x2; p++)
		fast_sp(p,y,color);
}



void drawline(int start_x, int start_y, int stop_x, int stop_y, unsigned long color) {

	//Lock(); assumes its locked

	
	int y_unit,x_unit;
	int ydiff = stop_y-start_y;
	if(ydiff<0)
	{
		ydiff = -ydiff;
		y_unit=-1;
	}
	else
	{
		y_unit =1;
	}
	int xdiff=stop_x-start_x;
	if(xdiff<0)
	{
		xdiff=-xdiff;
		x_unit = -1;
	}
	else
	{
		x_unit = 1;
	}
	
	int error_term=0;
	if(xdiff>ydiff)
	{
		int length=xdiff+1;
		for(int i = 0; i <length; i++)
		{
			//SetPixel(dc,start_x,start_y,color);

			//fast_sp(start_x,start_y,rect.Pitch,color);

			setpixel(buf, start_x, start_y, color, front->format->BitsPerPixel, front->pitch);
			start_x += x_unit;
			error_term+=ydiff;
			if(error_term>xdiff)
			{
				error_term-=xdiff;
				start_y+=y_unit;
			}
		}
	}
	else
	{
		int length = ydiff+1;
		for(int i = 0; i < length; i++)
		{
			//SetPixel(dc,start_x,start_y,color);

			//fast_sp(start_x,start_y,rect.Pitch,color);

			setpixel(buf, start_x, start_y, color, front->format->BitsPerPixel, front->pitch);
			start_y += y_unit;
			error_term+=xdiff;
			if(error_term>0)
			{
				error_term-=ydiff;
				start_x += x_unit;
			}
			
		}
	}
}

void drawtoptri(int x1, int y1,int x2, int y2, int x3, int y3, unsigned long color) {

	float dx_right,dx_left,xs,xe,height;  

	int temp_x,temp_y,right,left;

	if (x2 < x1) {
		temp_x = x2;
		x2     = x1;
		x1     = temp_x;
	}

	height = float(y3-y1);

	dx_left  = (x3-x1)/height;
	dx_right = (x3-x2)/height;

	xs = (float)x1;
	xe = (float)x2; 
	if (y1 < min_clip_y) {
		xs = xs+dx_left*(float)(-y1+min_clip_y);
		xe = xe+dx_right*(float)(-y1+min_clip_y);
		y1=min_clip_y;
	}

	if (y3>max_clip_y)
		y3=max_clip_y;

	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) {
		for (temp_y=y1; temp_y<=y3; temp_y++) {
			drawhline(int(xs),int(xs+(int)xe-xs+1),temp_y,color);
			xs+=dx_left;
			xe+=dx_right;
		} 
	}
	else {
		for (temp_y=y1; temp_y<=y3; temp_y++) {
			left  = (int)xs;
			right = (int)xe;
			xs+=dx_left;
			xe+=dx_right;
			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;
			}
			drawhline((int)left,(int)left+(int)right-left+1,temp_y,color);
		} 
	}
}

void drawgentri(int x0, int y0, int x1, int y1, int x2, int y2, D3DCOLOR color) {

	if( y1 < y0 )
	{
		Swap(y1, y0);
		Swap(x1, x0);
	}
	if( y2 < y0 )
	{
		Swap(y2, y0);
		Swap(x2, x0);
	}

	if( y1 < y2 )
	{
		Swap(y2, y1);
		Swap(x2, x1);
	}


	float xl_edge = (float)x0; 
	float xr_edge = (float)x0;
	float dxldy;
	float dxrdy;
	float dxdy1 = (float)(x2-x0)/(y2-y0);
	float dxdy2 = (float)(x1-x0)/(y1-y0);
	if( dxdy1 < dxdy2 )
	{
		dxldy = dxdy1;
		dxrdy = dxdy2;
	}
	else
	{
		dxldy = dxdy2;
		dxrdy = dxdy1;
	}

	for(int y=y0; y<y2; y++)
	{
		for(int x=int(xl_edge); x<int(xr_edge); x++)
		{
			fast_sp(x, y, color);
		}

		xl_edge = xl_edge + dxldy;
		xr_edge = xr_edge + dxrdy;

	}

	if( dxdy1 < dxdy2 )
	{
		dxldy = (float)(x2-x1)/(y2-y1);
	}
	else
	{
		dxrdy = (float)(x2-x1)/(y2-y1);
	}
	for(int y=y2; y<y1; y++)
	{
		for(int x=int(xl_edge); x<int(xr_edge); x++)
		{
			fast_sp(x,y,color);
		}

		xl_edge = xl_edge + dxldy;
		xr_edge = xr_edge + dxrdy;
	}
}

void drawbottomtri(int x1, int y1, int x2, int y2, int x3, int y3, D3DCOLOR color) {
	float dx_right,dx_left,xs,xe,height;     
	int temp_x,temp_y,right,left;
	if (x3 < x2) {
		temp_x = x2;
		x2     = x3;
		x3     = temp_x;
	}
	height = float(y3-y1);
	dx_left  = (x2-x1)/height;
	dx_right = (x3-x1)/height;

	xs = (float)x1;
	xe = (float)x1;
	if (y1 < min_clip_y) {
		xs = xs+dx_left*(float)(-y1+min_clip_y);
		xe = xe+dx_right*(float)(-y1+min_clip_y);
		y1 = min_clip_y;
	}

	if (y3 > max_clip_y)
		y3 = max_clip_y;

	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) {
		for (temp_y=y1; temp_y<=y3; temp_y++) {
			drawhline(int(xs),(int)xs+(int(xe-xs+1)),temp_y,color);
			xs+=dx_left;
			xe+=dx_right;

		} 
	}
	else
	{
		for (temp_y=y1; temp_y<=y3; temp_y++) {
			left  = (int)xs;
			right = (int)xe;
			xs+=dx_left;
			xe+=dx_right;

			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;
			}
			drawhline(int(left),(int)left+(int(right-left+1)),temp_y,color);
		}
	}
}

void drawtri(int x1, int y1,int x2, int y2, int x3, int y3, D3DCOLOR color) {
	int temp_x,temp_y,new_x;

	if ((x1==x2 && x2==x3)  ||  (y1==y2 && y2==y3))
		return;

	if (y2<y1) {
		temp_x = x2;
		temp_y = y2;
		x2     = x1;
		y2     = y1;
		x1     = temp_x;
		y1     = temp_y;
	}

	if (y3<y1) {
		temp_x = x3;
		temp_y = y3;
		x3     = x1;
		y3     = y1;
		x1     = temp_x;
		y1     = temp_y;
	}

	if (y3<y2) {
		temp_x = x3;
		temp_y = y3;
		x3     = x2;
		y3     = y2;
		x2     = temp_x;
		y2     = temp_y;

	} 
	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;


	if (y1==y2)  {
		drawtoptri(x1,y1,x2,y2,x3,y3,color);
	} 
	else
		if (y2==y3){
			drawbottomtri(x1,y1,x2,y2,x3,y3,color);
		} 
		else {
			new_x = x1 + (int)(0.5+(float)(y2-y1)*(float)(x3-x1)/(float)(y3-y1));
			drawbottomtri(x1,y1,new_x,y2,x2,y2,color);
			drawtoptri(x2,y2,new_x,y2,x3,y3,color);
		} 
}