Hi,

I have a grid, which contains cells that have several different properties.

struct fluidProperties1 {
float foo;
float bar;
};

and I create the grid as follows using a template

Grid2D<fluidProperties1> grid1;

Now, I want to pass the array formed only by the values of foo, and not by bar. This is for a texture in OpenGL
I pass grid1.foo to openGL, eg:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gridW, gridH, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid1.foo);

but, I get the error:

cannot convert `float' to `const GLvoid*' for argument `9' to `void glTexImage2D(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)'

Could anyone tell me what I may be doing wrong here?

Thanks

P.S I'm using boost.multiarray to create my grids.

Member Avatar for MonsieurPointer

It has to do with the passed parameter. The last parameter (which you passed as grid1.foo) is of type float, but GLvoid* is expected.

I thought that might be the case, but I had a native float* pointer, called float* fooGrid that I passed to glTexture2D earlier, and that worked fine.
Now, that I use boost.multiarray for my grid, it doesn't work. What has changed between the two?

Member Avatar for MonsieurPointer

In that case you passed a pointer to a float. Now you are just passing a float.

oh, that makes sense. It's when I have members of a struct / class that I want to pass as pointers or arrays that I struggle to understand, just as I am trying to do here.
Would you know how I would go about passing grid1.foo as a pointer?

This is how I've created my grid using boost:

typedef boost::multi_array<fluidCProperties, 2> array_type;
array_type grid1;

Thanks for your help so far!

Member Avatar for MonsieurPointer

You will need to pass the address of your variable, e.g.

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gridW, gridH, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&grid1.foo);

What that does though, is send the address of the first value of grid1.foo.

I would then need it to stride the sizeof(grid1), to get to the next element, which glTexImage2D does not allow.

Do you think it would be best to use glTexCoordPointer, as it provides the function to stride?

I will give it a try and report on it soon.
Thanks for your help though, it got me on the way to a solution

sorry, glTexCoordPointer is for the texture coordinates, and not the image data.
Any suggestions on how I could extract the texture image array consisting only of grid1.foo data to pass to glTexture2D?

Member Avatar for MonsieurPointer

Any suggestions on how I could extract the texture image array consisting only of grid1.foo data to pass to glTexture2D?

If you need to retrieve an array, then just using float as the data type is insufficient. There are several factors you need to consider:

  1. What kind of type the array has to be (e.g. float, int, ...) as well as the size (see #2)?
  2. Will the function allocate the array?

As I am unfamiliar with the OpenGL API, I am very restricted in helping you any further. Sorry!

The fluidProperties1 structure has only floats within it.
I create an array using:

boost::multi_array<fluidProperties1, 2> grid1;

Each element of grid1 would then contain the data of fluidProperties1.
I just need to pass the data for the elements corresponding to grid1.foo, as an array. grid1.foo are floats.

In answer to your questions:
1. The type of array I will be passing is a float, and I know the size. The number of elements is the same as grid1.
2. I pass the size along with the data for the array, so the function can allocate it.

I'm starting to understand that passing grid1.foo is not an option, so that would mean having to extract to a separate float array, before I can pass it onto the function. Is that correct?

Member Avatar for MonsieurPointer

Yes, it seems like it. My guess is that boost::multi_array is not compatible with the required parameter signature (GLvoid*), then again I am not sure because I am not very familiar with the boost library. If my hunch is right, then you will have to use a C-type array, e.g.

struct fluidProperties1 {
float foo[2];
float bar;
};

struct fluidProperties1 grid1;

Then pass the array to the function:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gridW, gridH, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid1.foo);

Is this what you mean?

What I meant is, if I had a struct with attributes, as below:

struct fluidProperties1{
float foo;
float bar;
};

Once I've created my array using boost multiarray with the fluidProperties1 as the template arguments, i.e.,

boost::multi_array<fluidProperties1, 2> grid1;

Then, I would have to:

float *fooArray;
for (int i = 0; i != grid1.size(); ++i)
     fooArray[i] = grid1[i].foo;

in order to extract the array, to then pass onto glTexImage2D:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gridW, gridH, 0, GL_RGBA, GL_UNSIGNED_BYTE, fooArray);

which I feel might defeat the object of what I was trying to do. I wanted to make this clear, but keep it efficient at the same time.

Initially, I had a separate array for each attribute in the fluidProperties1 structure. At that time, it was easy to just pass an array like fooArray straight to glTexImage2D.
I thought that by creating just one grid array, and having each element of this array store the attributes for the separate arrays I had earlier, would make the code clear. At the same time, I thought it would just be a case of passing grid1.foo to a function to pass an attribute of the object as a separate array. It's a lot more complicated than that it now seems. Do you think there is an efficient way of extracting the array, based on the way I've explained above?

I hope I've explained myself clearly. When you say I would have to use a C-type array, is that the same as what I had earlier, i.e., fooArray?

Member Avatar for MonsieurPointer

I think I finally understand what you are trying to accomplish.

When you say I would have to use a C-type array, is that the same as what I had earlier, i.e., fooArray?

Yes.

If it was possible, wouldn't it just be easier just to pass a C-type array of fluidProperties1 structs? Remember, once you've generated fooArray as you mentioned in your previous post, you will need to put those back in the structs, which is complicated.

If you can't, then the only solution I can currently think of is the solution which you have posted, e.g. create a temporary array which stores all of grid1's foo members, pass that to the OpenGL function, then place those back in the grid1 structs.

Here's one solution I obtained from a friend, and it worked exactly as I wanted. I'm posting this for those that might find it useful:

This is the 1D case for clarity:

// Store the fluid data
struct FluidData{
    std::vector<float> foos;
    std::vector<float> bars;
    FluidData(int n){foos.resize(n); bars.resize(n);) // CTor
};

// Individual fluid property
class FluidProperties{
    private float* foo;
    private float* bar;
    public void setPropertiesFromData(float* f, float*b){foo = f; bar = b;} // Ctor
    public float& foo(){return *foo;} // Reference to foo
    public float& bar(){return *bar;} // Reference to bar
};

And then:

// Create array and data
boost::multi_array<FluidProperties, 2> grid;
FluidData data(n); // Create the structure that stores the data

// Link the fluid properties with the data
for(int i=0; i<n; ++i){
    grid[i].setPropertiesFromData(&data.foos[i], &data.bars[i]);
}

The important thing is that now your foos and bars are in a contiguous chunk of memory, so you can easily call our opengl function:

// Now you can access/modify the data from the individual properties directly
for(int i=0; i<n; ++i){
    grid[i].foo() = 7;
    grid[i].bar() = 13;
}

// Do opengl stuff
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gridW, gridH, 0, GL_RGBA, GL_UNSIGNED_BYTE,  &data.foos[0]);
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.