why these 'if' seems ignored?

Pages: 123
see these code:
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
void DrawLine(int X0, int Y0, int Z0, int X1, int Y1, int 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(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 Pers = 300+Z;
            //Avoiding division by zero:
            if(Pers==0) Pers =1;
            float Perspective = 300/Pers;

            //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)
            {
                size_t pixelOffset = PosY * scanlineSize + PosX * pixelSize;
                if(pixelOffset<(Pixels.size()))
                {
                    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();
    }

now see these 'if':
1
2
3
4
5
6
7
8
9
10
11
            //Draw the pixel on valid positions:
            if(Z>=0 && PosX<=Width)
            {
                size_t pixelOffset = PosY * scanlineSize + PosX * pixelSize;
                if(pixelOffset<(Pixels.size()))
                {
                    Pixels[pixelOffset+2]=GetRValue(LineColor);
                    Pixels[pixelOffset+1]=GetGValue(LineColor);
                    Pixels[pixelOffset+0]=GetBValue(LineColor);
                }
            }

why i see the 'PosX<=Width' seems ignored?
i'm asking these because some pixels are drawed on left and others on right. seems that if the 'pixelOffset' is more big that the vector size, the index will restart from zero. can anyone explain why these behavior?
i just need avoid draw pixels more than Width-1
what are the values of all three variables when it is ignored (use a conditional breakpoint in your debugger or break inside the if and find a case where it got there against the condition).

What you will see is that the if works fine. It may have bad logic -- I can't tell -- but it is working. That means that your bug is either the condition itself or your logic somewhere else is damaging the memory/image. It could be as simple as not checking posy against top/bottom of image, or that one of the other variables has a bad value. for example: does PosY * scanlineSize know its true size (in bytes) or in pixels?
Last edited on
Cambalinho wrote:
why i see the 'PosX<=Width' seems ignored?
[...]
i just need avoid draw pixels more than Width-1

In that case you should write PosX < Width.
Last edited on
> if(Refresh==true) RefreshToHDC();
Mmmm.

https://cplusplus.com/forum/general/285030/

Maybe you should do a single refresh after drawing all the lines, and everything else you wanted to draw.

TBH, it would be nice for you to create a simple benchmark program that just draws say 10 random lines on screen as fast as possible.

It's hard to make optimisation recommendations without seeing the whole code. Especially when there seems to be elephants like this in the room.
i'm sorry to all. but i didn't getted the Notifications :(
have something to do been always longing even not be here?
i found several problems but fixed. the problem was not on 'DrawLine()', but on 'Width' and 'Height' and 'PosX' and 'PosY'.
- the code order for get the right size;
- the 'DrawLine()' parameters must be 'float' for be more easy... only the 'PosX' and 'PosY' are 'int', because the 'pixelOffset' must be 'int', because the array index it's an integer value type.
yes... sometimes i fail. sorry to all

Salem_c: take an easy.. ok... "It's hard to make optimisation recommendations without seeing the whole code. Especially when there seems to be elephants like this in the room." don't need be rude with people... i can fail... but i'm Human like you.
i never was rude with people and the forum have rules for it. so take an easy... i know that i can fail somethings and sorry but i wasn't notificated(maybe the Moderator can help me on these... and i'm using the Hotmail mail)...
when i show only that lines it because i thot that was enough... but i fail. sorry
of course you fail, we all do.
you have been at this or similar projects for a year or so, maybe more now, in these forums and have stuck with it, growing your code and skills along the way. Sticking with it is a big piece of getting better, and you get credit for that.

What Salem said should not be considered rude or mean. We have a couple of outright mean/rude people, and he isn't one of them. He is just stating facts ... its true that its hard to optimize it with only bits and pieces, and its true that trying to do so with an error like that (which indicates, as he said, that there could be other serious, similar problems that need addressing) is just a fact. You optimize code last or nearly last (it can be part of a repeating cycle at times), apart from the up front bits like picking the right algorithm and tools for the job as you design it. Debugging is in the middle, and until its debugged, optimization isnt going to work well. Take what he said in the spirit of trying to help you. I wouldn't want someone to try to optimize my code before I debugged it either, and if I asked for such, I would expect to get a 'debug it first' reply.
Last edited on
@Cambalinho, part of being good at s/w development is being able to step back from the coalface.

Creating side projects to explore one facet of the overall problem is just part of being a good developer.

So let's say you create your 100+ line benchmark program. You go on to discover one one two things:
1. It's amazingly fast, in which case you can compare the two examples and figure out where the critical differences are.
By slowly adding extra bits from your main program to your test program, you can figure out what exactly causes the performance breakdown.

2. It's just as slow, but now you have a chance to study what you did in isolation and test ideas to fix it.
Plus, if you're still stuck, you now have a short self contained example to post on forums for advice.

The edit / build / test cycles for a simple one-function program are so much faster than for a larger program.

Either way, you'll find out new information quicker than you would otherwise.

Success or failure isn't measured by how many keystrokes you make on any given day on the actual program.
Success or failure isn't measured by how many keystrokes you make on any given day on the actual program.


Very true...
Make it correct before you make it fast.
1 - thanks to all.
2 - make things working, we can... making the things faster is another story.
ok... we run out off-topic.. sorry to all.
Algorithm is the steps for resolve a problem. All Algorithms are different... what i never learned, only by forums\internet, is: how make faster Algorithms?
We must learn how calculate the FPS using, for example, the 'GetTickCount()':
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int FramePerSecond=0;
    int Frames=0;    
    auto Start =GetTickCount();//the start time
    do
    {
        Frames++; // count the number of frames
        auto Actual =GetTickCount();// get the actual time
        if((Actual-Start) >= 1000) //if it's a second..
        {
            Start = GetTickCount(); //change the start time
            FramePerSecond =Frames; //getting the number of frames after a second
            Frames=0; //reset the number of frames
        }

    }while(!(GetKeyState(VK_ESCAPE) & 0x8000));//until the escape key is pressed 

using these code we can test if the function is faster or not... but what is the best FPS?
that function draw a line using DIB's:
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;
    }
};

but i only get 280FPS... and seems low... i only drawed a line.
Last edited on
280 fps is notably faster than most monitors can draw. I think you can get around 250 in a high end monitor, but most people do not have that.

a typical high end 3-d game running at 80 FPS is considered to be pretty good.

drawing lines, though, isn't exactly taxing the system, its a simple operation and very high FPS is expected.

jonnin just using CPU and DIB's, we can't get better? or is my Algorithm?

Moderator: why i can't get notifications? is because i'm login with open separator browser?
time a time i do CTRL+F5 key pressing for see if someone answer me.
Last edited on
If you don't display it (?? is that what you are asking ??) then the monitor limits won't be in play.
> but i only get 280FPS... and seems low... i only drawed a line.
In a previous thread, you were down at 35FPS.
https://cplusplus.com/forum/general/285030/

So now you explore in your test bench possible ways of turning 280FPS into 35FPS by doing certain things. When you know what causes your FPS to fall off a cliff, you can adjust your main program to NOT do those things.

How does your FPS respond to increasing number of lines?
- 10 lines
- 100 lines
- 1000 lines
- 10000 lines
This is a simple
1
2
3
4
for ( int nlines = 1 ; nlines <= 10000 ; nlines *= 10 ) {
  // draw the requested number of lines and report the effective FPS
  doLineTest(nlines);
}


How does your FPS respond to increasing number of rectangles?
- 10 rectangles
- 100 rectangles
- 1000 rectangles
- 10000 rectangles

Are lines/rectangles the only thing your main application draws?

What is a representative number of lines/rectangles drawn in your main application?

Test that number in your test bench and compare the FPS result with your main application.
yes i did:
1
2
3
4
5
6
for(int i=0; i<100; i++)
        {
            test.DrawLine(line.OriginX, line.OriginY+i, line.OriginZ, line.DestinationX, line.DestinationY+i, line.DestinationZ,RGB(0,255,0), false);
        }
        test.RefreshToHDC();//these is for draw/update to HDC, only, when the pixel array is colored
        //these way i win speed or i get 18FPS kkkk lol 

i only get more or less 170 FPS. and it's like 1 wall but not texture, just filled with a color.


another test:
1
2
3
4
5
6
7
8
9
10
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.RefreshToHDC();
        for(int i=0; i<600; i++)
        {
            test.DrawLine(line.OriginX+600, line.OriginY+i, line.OriginZ, line.DestinationX+600, line.DestinationY+i, line.DestinationZ,RGB(0,255,0), false);
        }
        test.RefreshToHDC();

been the same and avoid several CPU, i only call the RefreshToHDC() once.
for now i get 31FPS.. with 2 flat green walls.
if i use the RefreshToHDC() 2 times, i will get the same FPS. but in these case i can win processing ;)
is how i create the rectangle. on image.DrawRectangle(...):
1
2
3
4
5
6
7
8
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();
    }

and yes, i can change the code for use tiled texture(using another image class variable with string parameter on constructor) ;)
Last edited on
updated with texture: https://imgur.com/JIGUwvm
Last edited on
now having 2 walls and the floor, i get 8 FPS lol
that's why i need understand what i can improve for get more speed
> updated with texture
Back off until you understand the problem more.

It's already broken for two plain walls and nothing else.

I'm assuming from your comments this draws two green walls.
1
2
3
4
5
6
7
8
9
10
11
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.RefreshToHDC();
for(int i=0; i<600; i++)
{
  test.DrawLine(line.OriginX+600, line.OriginY+i, line.OriginZ, line.DestinationX+600, line.DestinationY+i, line.DestinationZ,RGB(0,255,0), false);
}
//!! comment this out!
// test.RefreshToHDC(); 

Comment out the final RefreshToHDC();

You won't see anything on screen happening, but you'll still get an FPS value.

If it's still in ~30FPS range, then it's the actual line drawing that's the problem.
If it jumps back up to the 100++ FPS range, then RefreshToHDC is your problem.
doing these:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
        }

        for(int i=0; i<600; i++)
        {
          test.DrawLine(line.OriginX+600, line.OriginY+i, line.OriginZ, line.DestinationX+600, 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... so it can be the DrawLine() problem:
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
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 = 500;
            //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();
    }

what you can tell me more?
Pages: 123