1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
class image
{
public:
int Width = 0;
int Height = 0;
HDC HDCMemory;
HBITMAP HBit;
HBITMAP oldBit;
BITMAP bmp;
BITMAPINFO info;
size_t pixelSize;
size_t scanlineSize;
size_t bitmapSize;
vector<BYTE> Pixels;
image(int SizeWidth, int SizeHeight, COLORREF Backcolor=RGB(0,0,0))
{
//Creating HDC and HBITMAP memory:
HDCMemory = CreateCompatibleDC(NULL);
HBit = CreateBitmap(SizeWidth, SizeHeight, 1, 32,NULL);
SelectObject(HDCMemory, HBit);
//Getting image size:
Width = SizeWidth;
Height = SizeHeight;
//Clear image and change the backcolor:
Clear(Backcolor);
//Getting DIB's from HDC:
memset( &bmp, 0, sizeof(BITMAP) );
GetObject(HBit, sizeof(BITMAP), &bmp);
info.bmiHeader.biSize = sizeof(info.bmiHeader);
info.bmiHeader.biWidth = bmp.bmWidth;
// pay attention to the sign, you most likely want a
// top-down pixel array as it's easier to use
info.bmiHeader.biHeight = -bmp.bmHeight;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biCompression = BI_RGB;
// the following calculations work for 16/24/32 bits bitmaps
// but assume a byte pixel array
pixelSize = info.bmiHeader.biBitCount / 8;
// the + 3 ) & ~3 part is there to ensure that each
// scan line is 4 byte aligned
scanlineSize = (pixelSize * info.bmiHeader.biWidth + 3) & ~3;
bitmapSize = bmp.bmHeight * scanlineSize;
Pixels.resize (bitmapSize);
GetDIBits(HDCMemory, HBit, 0, bmp.bmHeight, &Pixels[0], &info, DIB_RGB_COLORS);
}
void RefreshFromHDC()
{
//Update the pixels array\vector from HDC:
GetDIBits(HDCMemory, HBit, 0, bmp.bmHeight, &Pixels[0], &info, DIB_RGB_COLORS);
}
void RefreshToHDC()
{
//Update the image from pixels array\vector:
SetDIBits(HDCMemory, HBit, 0, bmp.bmHeight, &Pixels[0], &info, DIB_RGB_COLORS);
}
~image()
{
SelectObject(HDCMemory, oldBit);
DeleteObject(HBit);
DeleteDC(HDCMemory);
}
void Clear(COLORREF backcolor = RGB(0,0,0))
{
HBRUSH HBrush = CreateSolidBrush(backcolor);
RECT rec={0,0,Width, Height};
FillRect(HDCMemory,&rec,HBrush);
DeleteObject(HBrush);
RefreshFromHDC();
}
void DrawRectangle(float X0, float Y0, float Z0, float X1, float Y1, float Z1, COLORREF LineColor = RGB(255,0,0))
{
DrawLine( X0, Y0, Z0, X1, Y0, Z1, LineColor,false);
DrawLine( X0, Y0, Z0, X0, Y1, Z0, LineColor,false);
DrawLine( X1, Y0, Z1, X1, Y1, Z1, LineColor,false);
DrawLine( X0, Y1, Z0, X1, Y1, Z1, LineColor,false);
RefreshToHDC();
}
void DrawLine(float X0, float Y0, float Z0, float X1, float Y1, float Z1, COLORREF LineColor = RGB(255,0,0), bool Refresh=true)
{
//Getting Line Distance(float results):
float DX = abs(X1 - X0);
float DY = abs(Y1 - Y0);
float DZ = abs(Z1 - Z0);
float LineDistance =abs( sqrt(pow(DX,2) + pow(DY,2) + pow(DZ,2)));
//Getting the Steps incrementation(float results):
float XSteps = DX/LineDistance;
float YSteps = DY/LineDistance;
float ZSteps = DZ/LineDistance;
//Draw Line using the Steps\ Incrementation:
float X = X0;
float Y = Y0;
float Z = Z0;
for(int i=0; i<LineDistance; i++)
{
//For every steps we calculate the perspective:
float EyeDistance = 300;
//Avoiding division by zero:
if(Z==0) Z=1;
float Perspective = EyeDistance/(EyeDistance+Z);
//The 3D to 2D convertion(i use 300 of eye distance, but we can change it):
int PosX = trunc(X*Perspective);
int PosY = trunc(Y*Perspective);
//Draw the pixel on valid positions:
if(Z>=0 && PosX<Width && PosX>=0 && PosY<Height && PosY>=0)
{
size_t pixelOffset = PosY * scanlineSize + PosX * pixelSize;
Pixels[pixelOffset+2]=GetRValue(LineColor);
Pixels[pixelOffset+1]=GetGValue(LineColor);
Pixels[pixelOffset+0]=GetBValue(LineColor);
}
//Increment steps(integer results):
X+=XSteps;
Y+=YSteps;
Z+=ZSteps;
}
if(Refresh==true) RefreshToHDC();
}
operator HDC()
{
return HDCMemory;
}
};
|