Axelill's picture

VBO using OpenTK

I tried to create VBO with openTK without success.

I've already implemented VBO in c++ so I think my initialization is quite correct.

It is maybe a wrong type of parameter. When I want to destroy the buffer it just go with an error telling me that my memory is mayb corrupted. Any idea??

public sealed class CIndexedTrianglesMesh : CMesh
    {
        Int32[] m_indexes;
        Single[] m_data;
 
        UInt32 m_gl_index_buffer;
        UInt32 m_gl_vertex_buffer;
 
        public CIndexedTrianglesMesh(String _name)
            : base(_name)
        {
        }
 
        ~CIndexedTrianglesMesh()
        {
            //GL.DeleteBuffers(1, ref m_gl_index_buffer);
           // GL.DeleteBuffers(1, ref m_gl_vertex_buffer);
        }
 
        public override void GLBuildObject()
        {
            GL.ARB.GenBuffers(1, out m_gl_index_buffer);
            GL.ARB.GenBuffers(1, out m_gl_vertex_buffer);
 
            IntPtr t1 = new IntPtr(m_data.Length * sizeof(Single));
            IntPtr t2 = new IntPtr(m_indexes.Length * sizeof(Int32));
 
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ARRAY_BUFFER_ARB, m_gl_vertex_buffer);
            GL.ARB.BufferData(GL.Enums.ARB_vertex_buffer_object.ARRAY_BUFFER_ARB, 
                t1, m_data, GL.Enums.ARB_vertex_buffer_object.DYNAMIC_DRAW_ARB);
 
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ELEMENT_ARRAY_BUFFER_ARB, m_gl_index_buffer);
            GL.ARB.BufferData(GL.Enums.ARB_vertex_buffer_object.ELEMENT_ARRAY_BUFFER_ARB,
                t2 , m_indexes, GL.Enums.ARB_vertex_buffer_object.DYNAMIC_DRAW_ARB);
 
        }
        public override void GLDrawObject()
        {
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ARRAY_BUFFER_ARB, m_gl_vertex_buffer);
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ELEMENT_ARRAY_BUFFER_ARB, m_gl_index_buffer);
 
            GL.EnableClientState(GL.Enums.EnableCap.VERTEX_ARRAY);
            GL.VertexPointer(3, GL.Enums.VertexPointerType.FLOAT, 8 * sizeof(Single), 0);
            //GL.EnableClientState(GL.Enums.EnableCap.NORMAL_ARRAY);
            //GL.NormalPointer(GL.Enums.NormalPointerType.FLOAT, 8 * sizeof(Single), 3 * sizeof(Single));
            //GL.EnableClientState(GL.Enums.EnableCap.TEXTURE_COORD_ARRAY);
            //GL.TexCoordPointer(2, GL.Enums.TexCoordPointerType.FLOAT, 8 * sizeof(Single), 6 * sizeof(Single));
 
 
            GL.DrawElements(GL.Enums.BeginMode.TRIANGLES, m_indexes.Length, GL.Enums.All.INT, 0);
 
            GL.DisableClientState(GL.Enums.EnableCap.TEXTURE_COORD_ARRAY);
            GL.DisableClientState(GL.Enums.EnableCap.NORMAL_ARRAY);
            GL.DisableClientState(GL.Enums.EnableCap.VERTEX_ARRAY);
         }

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Axelill's picture

Yes , tour application works I can see te cube.

So you said that the bug has been fixed in the current release (no use of unsafe)

the Fiddler.'s picture

Yes, the fix has been commited and will be included in the 0.3.13 release (next week).

Axelill's picture

update : I have downloaded the svn last version compile it and it works with

GL.DrawElements(GL.Enums.BeginMode.TRIANGLES, m_indexes.Length, GL.Enums.All.UNSIGNED_INT, m_indexes);

with just Vertexpointer.

If I add a Element_array_buffer and normalpointer and TexCoordPointer fatal error and I need to reboot my computer.

I was wondering why the VertexPointer has a intptr as last parameter and
normalpointer and TexCoordPointer have object as last parameter.

any ideas ?

Axelill's picture

reupdate :

the element_array_buffer works there is a problem with the normalpointer and TexCoordPointer :

GL.EnableClientState(GL.Enums.EnableCap.NORMAL_ARRAY);
GL.NormalPointer(GL.Enums.NormalPointerType.FLOAT, 8 * sizeof(Single), 3 * sizeof(Single));
GL.EnableClientState(GL.Enums.EnableCap.TEXTURE_COORD_ARRAY);
GL.TexCoordPointer(2, GL.Enums.TexCoordPointerType.FLOAT, 8 * sizeof(Single), 6 * sizeof(Single));

is this should be like this ?:

GL.EnableClientState(GL.Enums.EnableCap.NORMAL_ARRAY);
GL.NormalPointer(GL.Enums.NormalPointerType.FLOAT, 8 * sizeof(Single),(intptr)( 3 * sizeof(Single)));
GL.EnableClientState(GL.Enums.EnableCap.TEXTURE_COORD_ARRAY);
GL.TexCoordPointer(2, GL.Enums.TexCoordPointerType.FLOAT, 8 * sizeof(Single), (intptr)(6 * sizeof(Single)));

do not want to try ;) don't want to reboot again with a blue screen of the death.

Axel.

the Fiddler.'s picture

I was wondering why the VertexPointer has a intptr as last parameter and
normalpointer and TexCoordPointer have object as last parameter.

Actually, all of these functions (should) have both IntPtr and object overloads. In general, OpenGL functions that take "void*" parameters are translated in two C# functions: one taking an IntPtr (the moral equiavalent of void*), and one taking an object.

In this specific case, you want the IntPtr overloads - just put an (IntPtr) cast to make sure the correct overload is called (the second code sample you posted).

However, blue screens and reboots don't sound right in Vista, normally you'd only get a driver reset. This probably indicates a driver bug, updating may (or may not) improve stability.

Edit:
GL.DrawElements(GL.Enums.BeginMode.TRIANGLES, m_indexes.Length, GL.Enums.All.UNSIGNED_INT, m_indexes);
It's been some time since I used these, but are you sure this is correct? When using VBO's, the last parameter indicates an offset inside the uploaded data. Shouldn't that be:
GL.DrawElements(GL.Enums.BeginMode.TRIANGLES, m_indexes.Length, GL.Enums.All.UNSIGNED_INT, (IntPtr)0);?

The same thing regarding NormalPointer and TexCoordPointer - shouldn't the last parameter be (IntPtr)0?

Axelill's picture

Yep I have changed my code to the second case (using (intptr)) and it works fine.

thanks everyone for the support.
;-) Axel.

the Fiddler.'s picture

Ok, glad it works! :-)

Axelill's picture

nop the last parameter should not be (intptr)(0) because my m_data is in fact an array of float with position normal uvs...

so you need to show opengl where he can find the first correct data.

the Fiddler.'s picture

Aha, makes sense. (still catching up, last time I used OpenGL VBO's weren't yet in the spec - VA's and VAR's were the rage)

Axelill's picture

So Now that everything works, I think it might be a good idea to share the minimal code

So if you want to create a vbo:

public void GLBuildObject(Single[] m_data, UInt32[] m_indexes)
        {
            GL.ARB.GenBuffers(1, out m_gl_index_buffer);
            GL.ARB.GenBuffers(1, out m_gl_vertex_buffer);
 
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ARRAY_BUFFER_ARB, m_gl_vertex_buffer);
            GL.ARB.BufferData(GL.Enums.ARB_vertex_buffer_object.ARRAY_BUFFER_ARB,
                (IntPtr)(m_data.Length * sizeof(Single)), m_data, GL.Enums.ARB_vertex_buffer_object.STATIC_DRAW_ARB);
 
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ELEMENT_ARRAY_BUFFER_ARB, m_gl_index_buffer);
            GL.ARB.BufferData(GL.Enums.ARB_vertex_buffer_object.ELEMENT_ARRAY_BUFFER_ARB,
                (IntPtr)(m_indexes.Length * sizeof(UInt32)), m_indexes, GL.Enums.ARB_vertex_buffer_object.STATIC_DRAW_ARB);
 
            m_data = null;
            //m_indexes = null;
        }

and for the drawing

        public void GLDrawObject()
        {
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ARRAY_BUFFER_ARB, m_gl_vertex_buffer);
            GL.ARB.BindBuffer(GL.Enums.ARB_vertex_buffer_object.ELEMENT_ARRAY_BUFFER_ARB, m_gl_index_buffer);
 
                GL.EnableClientState(GL.Enums.EnableCap.VERTEX_ARRAY);
                GL.VertexPointer(3, GL.Enums.VertexPointerType.FLOAT, 8 * sizeof(Single), (IntPtr)(0));
                GL.EnableClientState(GL.Enums.EnableCap.NORMAL_ARRAY);
                GL.NormalPointer(GL.Enums.NormalPointerType.FLOAT, 8 * sizeof(Single), (IntPtr)(3 * sizeof(Single)));
                GL.EnableClientState(GL.Enums.EnableCap.TEXTURE_COORD_ARRAY);
                GL.TexCoordPointer(2, GL.Enums.TexCoordPointerType.FLOAT, 8 * sizeof(Single), (IntPtr)(6 * sizeof(Single)));
 
            GL.DrawElements(GL.Enums.BeginMode.TRIANGLES, m_indexes.Length, GL.Enums.All.UNSIGNED_INT, null);
 
                GL.DisableClientState(GL.Enums.EnableCap.TEXTURE_COORD_ARRAY);
                GL.DisableClientState(GL.Enums.EnableCap.NORMAL_ARRAY);
                GL.DisableClientState(GL.Enums.EnableCap.VERTEX_ARRAY);
        }

Hope it can help someone else.