how send a function array parameter?

Apr 3, 2022 at 8:50pm
heres how i call the function:
1
2
3
 unsigned int PixelColors[ConsoleHeight][ConsoleWidth];
// draw a line:
        DrawLine3D(PixelColors,RotOrigin,RotDestination, RGB(0,255,0) );

the function:
1
2
3
4
5
6
7
8
9
10
11
void DrawLine3D(unsigned int *&Pixels, Position3D Origin, Position3D Destination, COLORREF Color)
{
    std::vector<Position3D> GetLineDots = GetLinePoints(Origin, Destination);
    for(int x=0; x<GetLineDots.size()-1; x++)
    {
        unsigned int X = GetLineDots[x].PosX;
        unsigned int Y = GetLineDots[x].PosY;

        Pixels[X] [Y] = Color;
    }
}

i get an error on 'Pixels[X] [Y] = Color;': "invalid types 'unsigned int[unsigned int]' for array subscript".
how can i fix the code?
'PosX' and 'PosY' are float types
Last edited on Apr 3, 2022 at 8:51pm
Apr 3, 2022 at 10:53pm
Pixels is a pointer to unsigned int, but you're trying to dereference it twice. If you need to flatten a 2D coordinate for rectangular data, you'd do something like:
1
2
size_t index = width * y + x;
Pixels[index] = value;


PS: Passing Pixels as a reference is unnecessary since you never overwrite the value of Pixels itself.
Last edited on Apr 3, 2022 at 10:55pm
Apr 4, 2022 at 9:35pm
'DrawLine3D()' don't recive size parameters.
if i do 'void DrawLine3D(unsigned int Pixels[],'.. works but the array have only 1 dimension... but how i change for 2 dimensions?
Apr 4, 2022 at 9:50pm
"unsigned int Pixels[]" and "unsigned int* Pixels" as function parameters mean the same exact thing, it's just syntax sugar to use the [].

As seen in your other thread, the Win32 call StretchDIBits inevitably expects the lpBits data to be representable as one contiguous 1D array. So you can cast the 2D array to fake it as a 1D pointer, or you could just have a 1D array to begin with.(*) The latter seems simpler to me, but I guess either way works.

You own the DrawLine3D function. Add a parameter that tells the function what the width is. Pass in ConsoleWidth tp DrawLines3D, then you can do
pixels[y * ConsoleWidth + x] = Color;

Also,
1
2
3
4
5
6
7
    operator Position2D()
    {
        Position2D Pos2D{PosX, PosY};
        Pos2D.PosX = PosX;
        Pos2D.PosY = PosY;
        return Pos2D;
    }

This is redundant. You could just do
1
2
3
4
    operator Position2D()
    {
        return Pos2D{PosX, PosY};
    }



(*)This is what I mean here. Again, it appears to not be necessary, but would prevent unnecessary weird casts.
1
2
3
4
5
6
7
8
9
10
11
unsigned int PixelColors[ConsoleHeight * ConsoleWidth];

// ...

for(int y=0; y<ConsoleHeight; y++)
{
    for(int x=0; x<ConsoleWidth; x++)
    {
        PixelColors[y * ConsoleWidth + x] = RGB(0,0,255);
    }
}
Last edited on Apr 4, 2022 at 9:56pm
Apr 4, 2022 at 10:00pm
i'm so sorry, but can i pass a 2D array or vector for a parameter function?
Apr 4, 2022 at 10:05pm
As long as ConsoleWidth is a global constant, you can do this:

 
void DrawLine3D(unsigned Pixels[][ConsoleWidth], etc...)


Apr 4, 2022 at 10:06pm
can i do it without the 'ConsoleWidth' on parameter declaration?
Apr 4, 2022 at 10:28pm
With array, no. You need the non-inner dimension so the compiler knows the pointer offsets.

With vector, yes. You can pass a vector of vectors as a parameter, and then query the .size() of each inner vector to know the width. But this is (1) less efficient since each vector is a separate allocation, and (2) not compatible with what StretchDIBits requires, since it requires one contiguous array.

What is so bad about adding a parameter to DrawLine3D, since you are able to change the function signature?
Last edited on Apr 4, 2022 at 10:29pm
Apr 4, 2022 at 10:31pm
Are you saying that ConsoleHeight and ConsoleWidth are not constant?
That is a non-standard extension to C++ from C99.

Anyway, you could flatten the array and do the 2D calculation in the function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void DrawLine3D(unsigned *pixels, unsigned height, unsigned width)
{
    for (unsigned h = 0; h < height; h++)
    {
        for (unsigned w = 0; w < width; w++)
        {
            unsigned i = h * width + w;
            cout << pixels[i] << ' ';
        }
        cout << '\n';
    }
}

// call it like this:
    DrawLine3D((unsigned*)pixels, height, width);
Apr 4, 2022 at 11:06pm
You can use standard C++ with a 1D vector that you treat as 2D.
This is efficient since all data is in one block.

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
#include <iostream>
#include <vector>
using namespace std;

void Print2D(const vector<unsigned>& pixels, unsigned width)
{
    unsigned height = pixels.size() / width;
    for (unsigned h = 0; h < height; h++)
    {
        unsigned rowstart = h * width;
        for (unsigned w = 0; w < width; w++)
        {
            unsigned i = rowstart + w;
            cout << pixels[i] << ' ';
        }
        cout << '\n';
    }
}

int main()
{
    unsigned height, width;
    cin >> height >> width;

    vector<unsigned> pixels(height * width);

    for (unsigned h = 0; h < height; h++)
        for (unsigned w = 0; w < width; w++)
            pixels[h * width + w] = 0;

    Print2D(pixels, width);
}

Apr 5, 2022 at 1:11am
All good suggestions. Only thing that remains is figuring out why Cambalinho doesn't want to pass the width as a parameter, solving all his problems.
Apr 5, 2022 at 8:28pm
Ganado: "All good suggestions. Only thing that remains is figuring out why Cambalinho doesn't want to pass the width as a parameter, solving all his problems."
i'm sorry... but why not be more automatic and simple? is what i think... i can add more parameters on function... but i need be more simple ;)
thanks to all.. but i'm trying using:
std::vector<std::vector<unsigned >> PixelColors{{ConsoleWidth},{ConsoleHeight}};
but when i do:
1
2
3
4
5
6
7
for(int y=0; y<ConsoleHeight; y++)
        {
            for(int x=0; x<ConsoleWidth; x++)
            {
                PixelColors[y][x] = RGB(0,0,255);
            }
        }

i get these error when the program terminates\frezes:
"Process returned -1073740940 (0xC0000374) execution time : 0.025 s
Press any key to continue."
i'm doing wrong with 'PixelColors[y][x]' or with 'PixelColors{{ConsoleWidth},{ConsoleHeight}}'?
Apr 5, 2022 at 8:51pm
i did wrong the 2D vector creation:
std::vector<std::vector<unsigned int>> PixelColors( ConsoleHeight , std::vector<unsigned int> (ConsoleWidth, 0));
even on value i must use the 'vector'.
now i did another topic for convert 2D vector to void*.
thank you so much for all
Apr 5, 2022 at 9:27pm
i'm sorry... but why not be more automatic and simple? is what i think... i can add more parameters on function... but i need be more simple ;)

1D array is "simpler" than 2D array.

You lament that creating and filling 1D is "too complex". Yet, isn't the ultimate goal to call a function that expects 1D (void *) array?

If the data will be consumed as 1D array in a function that you can't modify, then isn't 1D array exactly what should offer it?
Apr 5, 2022 at 9:50pm
i'm learning and understand on hard way... but now i know the void* is 1D array pointer.
thank you so much for all
Apr 5, 2022 at 10:24pm
The Microsoft documentation of the function says:
[in] lpBits

const void*
A pointer to the image bits, which are stored as an array of bytes.

Now you know that "array" means "array" -- at least in this context.
Apr 7, 2022 at 8:00pm
thanks for the correction to all.. thank you
Topic archived. No new replies allowed.