why these 'if' seems ignored?

Pages: 123
Nov 15, 2022 at 5:28pm
doing these:
1
2
3
4
5
6
7
8
9
/*
            //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);
            }*/

i win a double speed.
and yes i found a problem here... why using GetXValue() inside the loop, if i can do it outside!?!
i will test these now
Nov 15, 2022 at 5:30pm
> i get 16FPS... so it can be the DrawLine() problem:
Not until you also time it WITHOUT calling RefreshToHDC();

You're measuring 16FPS doing both things.

You need to find out whether it's one or the other.

Nov 15, 2022 at 5:38pm
using these:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
do
    {
        test.Clear();
        string s="Frame Per Second: " + to_string(FramePerSecond);
        DrawText(test,s.c_str(),-1, &rec2, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        test.RefreshFromHDC();
        int TextureY=0;
        for(int i=0; i<600; i++)
        {
          test.DrawLine(line.OriginX, line.OriginY+i, line.OriginZ, line.DestinationX, line.DestinationY+i, line.DestinationZ,RGB(0,255,0), false);
          test.DrawLine(line.OriginX+900, line.OriginY+i, line.OriginZ, line.DestinationX+900, line.DestinationY+i, line.DestinationZ,RGB(0,255,0), false);
        }
        test.RefreshToHDC();
        BitBlt(HDCConsole,50,0,test.Width, test.Height,test,0,0,SRCCOPY);

i get 16FPS. comment the 'test.RefreshToHDC();' or not.. the FPS is the same.
i change the DrawLine():
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
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;
        float EyeDistance = 500;// doing these i avoid the black\empty vertical lines

        //Getting RGB from the color:
        BYTE R = GetRValue(LineColor);
        BYTE G = GetGValue(LineColor);
        BYTE B = GetBValue(LineColor);

        for(int i=0; i<LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            //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;
                int PosR = pixelOffset+2;
                int PosG = pixelOffset+1;
                int PosB = pixelOffset+0;
                Pixels[PosR]=R;
                Pixels[PosG]=G;
                Pixels[PosB]=B;
            }


            //Increment steps(integer results):
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }
        if(Refresh==true) RefreshToHDC();
    }

what i'm changing is on loop:
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
for(int i=0; i<LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            //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;
                int PosR = pixelOffset+2;
                int PosG = pixelOffset+1;
                int PosB = pixelOffset+0;
                Pixels[PosR]=R;
                Pixels[PosG]=G;
                Pixels[PosB]=B;
            }


            //Increment steps(integer results):
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }

if i comment the 'if', i will get the 33FPS.
what is the 'Pixels' is a vector:
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
vector<BYTE> Pixels;

    void GetDIBS()
    {
        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);
    }

i'm doing wrong using a vector instead the 'void*'?
Nov 16, 2022 at 9:47am
anyone can tell me more? did i miss something?
1
2
3
4
5
6
7
8
9
10
11
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);
    }
Last edited on Nov 16, 2022 at 10:06am
Nov 16, 2022 at 12:43pm
if i comment the 'if', i will get the 33FPS.
Actually I doubt that this small piece of code has that much of an impact. You may surround the loop with GetTickCount() to exactly measure the time.

I recommend the following:
1
2
3
4
5
6
7
8
9
10
11
        BITMAPINFO bmi;
        memset(&bmi, 0, sizeof(bmi));
        bmi.bmiHeader.biSize = sizeof(bmi);
        bmi.bmiHeader.biWidth = cx;
        bmi.bmiHeader.biHeight = cy;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 32;
        bmi.bmiHeader.biCompression = BI_RGB;

        void *ptr;
        HBITMAP hb = CreateDIBSection(HDC{}, &bmi, DIB_RGB_COLORS, &ptr, 0, 0);
In that case you can modify the memory directly and select the HBITMAP into your memory DC for BitBlt(...) instead of permanently copying all pixels with GetDIBits(...)/SetDIBits(...).

By the way. Line 7 in DrawLine(...):
1
2
        float LineDistance =(DX * DX) + (DY * DY) + (DZ * DZ);
        if(LineDistance < 1) return;
Last edited on Nov 16, 2022 at 12:59pm
Nov 16, 2022 at 1:21pm
1 - your math ideia don't works :(
2 - using the void*ptr... how i use 'ptr[index]'? or i must allways 'ptr++'? to be honest the 'void*' continues make me confused.
Nov 16, 2022 at 2:34pm
1 - your math ideia don't works :(
The sqrt(...) was missing:
float LineDistance =sqrt((DX * DX) + (DY * DY) + (DZ * DZ));


2 - using the void*ptr... how i use 'ptr[index]'? or i must allways 'ptr++'? to be honest the 'void*' continues make me confused.
Instead of void * you may use uchar8_t (or whatever you prefer). However CreateDIBSection(...) expects a void** to fill. So you need a reinterpret_cast<void *>(ptr):
1
2
        //uchar8_t *Pixels;
        HBITMAP hb = CreateDIBSection(HDC{}, &bmi, DIB_RGB_COLORS, &reinterpret_cast<void *>(Pixels), 0, 0);
Nov 16, 2022 at 3:02pm
unsigned char *Pixels;

my CodeBlocks GNU compiler don't have the 'uchar8_t' only typedif ;)
HBit = CreateDIBSection(HDCMemory, &info, DIB_RGB_COLORS, &reinterpret_cast<void *>(Pixels), 0, 0);
error on 'reinterpret_cast':
"lvalue required as unary '&' operand"
so what is wrong?
Nov 16, 2022 at 3:21pm
Looks like you can't use &reinterpret_cast<void *>(Pixels) like this. So you unfortunately need to do this:

1
2
void* p = reinterpret_cast<void *>(Pixels);
HBit = CreateDIBSection(HDCMemory, &info, DIB_RGB_COLORS, &p, 0, 0);
Nov 16, 2022 at 3:33pm
or i did something wrong, or continues with no correct pointer:
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
BYTE *Pixels;

    void GetDIBS()
    {
        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* p = reinterpret_cast<void *>(Pixels);
        HBit = CreateDIBSection(HDCMemory, &info, DIB_RGB_COLORS,&p, 0, 0);
    }
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;



        GetDIBS();
        cout << "hey";
        //Clear image and change the backcolor:
        Clear(Backcolor);
    }

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

for test i use the 'Clear()':
1
2
3
4
do
    {
        test.Clear(RGB(255,0,0));
BitBlt(HDCConsole,50,0,test.Width, test.Height,test,0,0,SRCCOPY);

but nothing happens.. only 'cout', image(), works
Last edited on Nov 16, 2022 at 3:34pm
Nov 17, 2022 at 6:42am
You need to select HBit into your HDCMemory otherwise there is no bitmap to fill. So uncomment line 35 and move it after line 43.
Remove line 74.
Nov 17, 2022 at 7:02am
I'm wondering what your frame rate is for
1
2
3
4
5
6
7
8
do
    {
        test.Clear();
        string s="Frame Per Second: " + to_string(FramePerSecond);
        DrawText(test,s.c_str(),-1, &rec2, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        test.RefreshFromHDC();
        test.RefreshToHDC();
        BitBlt(HDCConsole,50,0,test.Width, test.Height,test,0,0,SRCCOPY);

This is the best it's going to be, even if you could magically draw the scene in zero time.

1
2
3
4
5
6
7
8
    void Clear(COLORREF backcolor = RGB(0,0,0))
    {
        HBRUSH HBrush = CreateSolidBrush(backcolor);
        RECT rec={0,0,Width, Height};
        FillRect(HDCMemory,&rec,HBrush);
        DeleteObject(HBrush);  // why?
        RefreshFromHDC();  // why!?
    }

Create the background clearing brush just once in the constructor, then delete it in the destructor. You're trying to write performance code, so don't keep creating and destroying things you can easily keep.

Also, what's with all the refreshing to/from HDC for?
Your loop should be
- clear your offscreen buffer
- draw in your offscreen buffer
- refresh offscreen buffer to the screen.



> void* p = reinterpret_cast<void *>(Pixels);
> HBit = CreateDIBSection(HDCMemory, &info, DIB_RGB_COLORS,&p, 0, 0);
Read the spec.
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdibsection

[out] ppvBits
A pointer to a variable that receives a pointer to the location of the DIB bit values.

p is updated to point to where the DIB is.

1
2
3
void* p;
HBit = CreateDIBSection(HDCMemory, &info, DIB_RGB_COLORS, &p, 0, 0);
Pixels = reinterpret_cast<BYTE*>(p);


Any chance you could upload this testbench code to say github?
Because we're back to trying to peephole optimise your code again.
Nov 17, 2022 at 7:58am
@salem c
You are right. void* p = reinterpret_cast<void *>(Pixels); was nonsense. Testing here is somewhat difficult...
Nov 17, 2022 at 8:54pm
1
2
3
4
5
6
7
8
9
10
11
12
image(int SizeWidth, int SizeHeight, COLORREF Backcolor=RGB(0,0,0))
    {
        //Creating HDC:
        HDCMemory = CreateCompatibleDC(NULL);


        //Getting image size:
        Width = SizeWidth;
        Height = SizeHeight;

        GetDIBS();
    }

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
void* p;
    BYTE *Pixels;

    void GetDIBS()
    {

        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;

        HBit = CreateDIBSection(HDCMemory, &info, DIB_RGB_COLORS, &p, 0, 0);
        if(SelectObject(HDCMemory, HBit)==NULL) cout << "error";
        Pixels = reinterpret_cast<BYTE*>(p);
    }

on test, i only draw the text FPS for see the result. but i miss something.
because nothing happens.. i get that 'cout' error
Nov 17, 2022 at 9:10pm
i found my image size error. and fixed... now i'm continue with change ;)
Nov 17, 2022 at 9:27pm
ok now i did a test:
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
int main()
{
    HDC HDCConsole = GetConsoleHDC();

    RECT rec;
    GetClientRect(GetConsoleWindow(),&rec);

    int Speed=1;
    LineSteps line(20,100,100,700,100,700);
    image test(1000,600);

    int FramePerSecond=0;
    int Frames=0;
    RECT rec2 ={0,30,170,50};
    auto Start =GetTickCount();
    do
    {
        test.Clear();
        string s="Frame Per Second: " + to_string(FramePerSecond);
        DrawText(test,s.c_str(),-1, &rec2, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        test.RefreshFromHDC();
        int TextureY=0;

        for(int i=0; i<600; i++)
        {
          //test.DrawLine(line.OriginX, line.OriginY+i, line.OriginZ, line.DestinationX, line.DestinationY+i, line.DestinationZ,RGB(255,0,0),false);
        }
        //test.RefreshToHDC();
        BitBlt(HDCConsole,50,0,test.Width, test.Height,test,0,0,SRCCOPY);

i 850-900FPS
now uncomment that 2 lines:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
LineSteps line(20,100,100,700,100,700);
    image test(1000,600);

    int FramePerSecond=0;
    int Frames=0;
    RECT rec2 ={0,30,170,50};
    auto Start =GetTickCount();
    do
    {
        test.Clear();
        string s="Frame Per Second: " + to_string(FramePerSecond);
        DrawText(test,s.c_str(),-1, &rec2, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        test.RefreshFromHDC();
        int TextureY=0;

        for(int i=0; i<600; i++)
        {
          test.DrawLine(line.OriginX, line.OriginY+i, line.OriginZ, line.DestinationX, line.DestinationY+i, line.DestinationZ,RGB(255,0,0),false);
        }
        test.RefreshToHDC();
        BitBlt(HDCConsole,50,0,test.Width, test.Height,test,0,0,SRCCOPY);

now get 56FPS.
seems that using the CreateDIBSection() i don't need update the image on HDC with image array.. thank you...
so only remains the DrawLine():
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
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 = X1 - X0;
        float DY = Y1 - Y0;
        float DZ = Z1 - Z0;
        float LineDistance =sqrt((DX * DX) + (DY * DY) + (DZ * DZ));


        //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;
        float EyeDistance = 500;// doing these i avoid the black\empty vertical lines

        //Getting RGB from the color:
        BYTE R = GetRValue(LineColor);
        BYTE G = GetGValue(LineColor);
        BYTE B = GetBValue(LineColor);

        for(int i=0; i<LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            //Avoiding division by zero:
            if(Z==0) Z=1;
            float Perspective = EyeDistance/(EyeDistance+Z);

            //The 3D to 2D convertion(i use 400 of eye distance, but we can change it... seems the better value for avoid the vertical black lines):

            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;
                int PosR = pixelOffset+2;
                int PosG = pixelOffset+1;
                int PosB = pixelOffset+0;
                Pixels[PosR]=R;
                Pixels[PosG]=G;
                Pixels[PosB]=B;
            }


            //Increment steps:
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }
    }


so is the entire math on function?
Nov 18, 2022 at 8:43am
so only remains the DrawLine():
What is the problem?

Some minor:
1
2
3
4
5
        float DX = X1 - X0;
        float DY = Y1 - Y0;
        float DZ = Z1 - Z0;
        float LineDistance =sqrt((DX * DX) + (DY * DY) + (DZ * DZ));
if(LineDistance < 1) return; // otherwise you risk a division by zero on line 11/12/13 


1
2
3
4
5
6
            //For every steps we calculate the perspective:
            //Avoiding division by zero:
//            if(Z==0) Z=1;
//            float Perspective = EyeDistance/(EyeDistance+Z);
const float d = EyeDistance+Z; // Note that Z==0 is irrelevant here
const float Perspective = (d != 0) ? (EyeDistance/d) : 0;
Nov 18, 2022 at 10:37pm
i need to ask: do i need convert float to int?

1
2
3
//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);

without trunc() i can win ~20 frames.
Nov 18, 2022 at 10:59pm
Truncation happens automatically when you convert a floating-point value to an integer. No need to call std::trunc.
Nov 18, 2022 at 11:08pm
thanks for that.. more 1 that i have learned with these code ;)
even so i have these slow... so i test more and i found that i lose 600FPS here:
these loop have 900 cycles... even so it's slow.. is these normal?

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
for(int i=0; i<LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            //Avoiding division by zero:
            const float d = EyeDistance+Z; // Note that Z==0 is irrelevant here
            const float Perspective = (d != 0) ? (EyeDistance/d) : 0;

            //The 3D to 2D convertion(i use 300 of eye distance, but we can change it):
            int PosX = X*Perspective;
            int PosY = 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;
                int PosR = pixelOffset+2;
                int PosG = pixelOffset+1;
                int PosB = pixelOffset+0;
                Pixels[PosR]=R;
                Pixels[PosG]=G;
                Pixels[PosB]=B;
            }


            //Increment steps(integer results):
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }

unless: is possible these math give me some igual values?(not tested, just thinking)
1
2
3
X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;

Pages: 123