PDA

View Full Version : Problem with glDrawArrays() in .NET



Frostie
02-14-2007, 04:28 AM
Hello!
I tried to display some data just like a plot or spectra data.
I thought pixel reuse is unimportant here so I choosed glDrawArrays. But all I get is one pixel at (0,0,0).

The drawing part of my code looks like this:


object[] data2=new object[] { 0.5, 0.5, 0.0 };
GL.glEnableClientState(GL.GL_VERTEX_ARRAY);
GL.glVertexPointer(3, GL.GL_FLOAT,0*sizeof(double), data2);
GL.glColor3f(0.0f, 1.0f, 0.0f);
GL.glDrawArrays(GL.GL_POINTS, 0, 1);

GL.glColor3f(1.0f, 1.0f, 1.0f);
GL.glBegin(GL.GL_POINTS);
GL.glVertex3f(1.0f, 0.0f, 0.0f);
GL.glVertex3f(0.0f, 1.0f, 0.0f);
GL.glEnd();


As you can probably see I use a .NET base class I found at Nehe to display some OpenGL from within .NET. This works quite well. To be sure that I set up all the initialisation correct I added the 5 lines at the end.
I see the two pixels just as I wanted. The commands at the top only draw 1 pixel at (0,0,0). They do that with the right color (green) but always at the center of my coordinates (0,0,0) - no matter what values data2 contains.

That's a little bit frustrating. I am not sure if this has something to do with the object array I need for the Nehe implementation of glDrawArrays. Maybe someone else tried this...?

RigidBody
02-14-2007, 04:35 AM
have you tried it with a static array like

float data2[]={0.5, 0.5, 0.0};

Frostie
02-14-2007, 10:11 AM
I tried it but the result is the same.
I don't think it should make a difference as this is coded in C# (I forgot to mention that).

Zengar
02-15-2007, 12:19 AM
The problem may be that .NET uses managed memory approach, meaning that objects can be freely moved around in the memory. Your data2 variable is converted to a pointer, but this pointer may be not valid some moments later (it also may be that the variable is deleted automatically). You should pin the object address using the GCHandle class (there are examples in MSDN library)

Joseph Steel
02-15-2007, 12:23 AM
Is the data (object) a float array (or equivalent)? You're saying that the data are floats (GL_FLOAT) but using sizeof(double), which suggests the data is double?

Frostie
02-15-2007, 11:44 AM
Problem solved!

I should have tried that earlier: I changed the declaration in the Nehe file from an object array to a simple double array :

[DllImport(GL_DLL,EntryPoint ="glVertexPointer")]
public static extern void glVertexPointer(int size, uint type, int stride, double[] pointer);

In the same way I changed my code an now it seems to work. At least I can see my green pixel between the two I draw manually.

Thanks for the help.

Zengar
02-15-2007, 12:01 PM
Still, I would advice you to declare pointer as IntPtr and use GCHandle to pin the object. In a more complex application, you will loose the data very soon.

Frostie
02-15-2007, 11:04 PM
I will take a look at it. But normally I wouldn't guess any problems as the rendering routine is a method of my OpenGL component (class). As long as this instance is alive I would not think that any member of it would be a victim of the garbage collector, right?
...
Hmm... but maybe it would be pushed to another adress. Is this what you mean? That would be really bad :-)
Ok, I think I really have to look at this GCHandle stuff.
Thanks.

RigidBody
02-16-2007, 01:10 AM
Originally posted by Frostie:
I should have tried that earlier: I changed the declaration in the Nehe file from an object array to a simple double array :

[DllImport(GL_DLL,EntryPoint ="glVertexPointer")]
public static extern void glVertexPointer(int size, uint type, int stride, double[] pointer);something seems to be wrong there. glVertexPointer should use a const GLvoid * pointer, not a double pointer.

the type of data in the array is defined by passing GL_FLOAT, GL_DOUBLE, GL_INT or GL_SHORT to glVertexPointer.

Frostie
02-16-2007, 02:10 AM
Ok, then the original declaration with an object array would make sense. But why is it working with double and not with object...?

It would be interesting to see if anyone has done an application based on the NeHe base class in .Net and used this function.

RigidBody
02-16-2007, 02:38 AM
sorry- i don't know anything about c# and its objects
and most probably, i never will ;)

Zengar
02-16-2007, 05:10 AM
It is all about how .NET transforms the data for native calls. Type 'object' will be most probably passed as pointer, thus 'object[]' will be array of pointers. Declaration like 'double[]' will work, because double is a struct type and not an object, hence resulting in a pointer to array of doubles. The best declaration would be 'IntPtr' or 'object'. Actually, if using .NET, it makes much sense to use VBOs.

P.S. object[] data2=new object[] { 0.5, 0.5, 0.0 } will create array of doubles and not floats.

Frostie
02-16-2007, 05:43 AM
VBOs? Never heard of them.
I will try to find some information about it.

Actually I did a cast to double of the init values in my array.

RigidBody
02-16-2007, 05:48 AM
Vertex
Buffer
Objects

are just vertex arrays which reside permanently in the graphics card memory. they are not transferred via the bus each frame, which results in better performance.