Refactoring an immediate drawing function into VBO, access violation error

Alex
  • Refactoring an immediate drawing function into VBO, access violation error Alex

    I have a MD2 model loader, I am trying to substitute its immediate drawing function with a Vertex Buffer Object one....

    I am getting a really annoying access violation reading error and I can't figure out why, but mostly I'd like an opinion as to whether this looks correct (never used VBOs before).

    This is the original function (that compiles ok) which calculates the keyframe and draws at the same time:

    glBegin(GL_TRIANGLES);
        for(int i = 0; i < numTriangles; i++) {
            MD2Triangle* triangle = triangles + i;
            for(int j = 0; j < 3; j++) {
                MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
                MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
                Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
                Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
                if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
                    normal = Vec3f(0, 0, 1);
                }
                glNormal3f(normal[0], normal[1], normal[2]);
    
                MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
                glTexCoord2f(texCoord->texCoordX, texCoord->texCoordY);
                glVertex3f(pos[0], pos[1], pos[2]);
            }
        }
    glEnd();
    

    What I'd like to do is to calculate all positions before hand, store them in a Vertex array and then draw them. This is what I am trying to replace it with (in the exact same part of the program)

    int vCount = 0;
        for(int i = 0; i < numTriangles; i++) {
            MD2Triangle* triangle = triangles + i;
            for(int j = 0; j < 3; j++) {
                MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
                MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
                Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
                Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
                if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
                    normal = Vec3f(0, 0, 1);
                }
    
                indices[vCount] = normal[0];
                vCount++;
                indices[vCount] = normal[1];
                vCount++;
                indices[vCount] = normal[2];
                vCount++;
    
                MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
                indices[vCount] = texCoord->texCoordX;
                vCount++;
                indices[vCount] = texCoord->texCoordY;
                vCount++;
    
                indices[vCount] = pos[0];
                vCount++;
                indices[vCount] = pos[1];
                vCount++;
                indices[vCount] = pos[2];
                vCount++;
            }
    
        }
    
             totalVertices = vCount;
    
            glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_VERTEX_ARRAY);
    
    
        glNormalPointer(GL_FLOAT, 0, indices);
        glTexCoordPointer(2, GL_FLOAT, sizeof(float)*3, indices);
        glVertexPointer(3, GL_FLOAT, sizeof(float)*5, indices);
    
    
        glDrawElements(GL_TRIANGLES, totalVertices, GL_UNSIGNED_BYTE, indices);
    
        glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
    

    First of all, does it look right?

    Second, I get access violation error "Unhandled exception at 0x01455626 in Graphics_template_1.exe: 0xC0000005: Access violation reading location 0xed5243c0" pointing at line 7

    Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
    

    where the two Vs seems to have no value in the debugger.... Till this point the function behaves in exactly the same way as the one above, I don't understand why this happens?

    Thanks for any help you may be able to provide!

    EDIT ----------------------------------------------------------------------------------

    Thank you Zacharmarz for your guidance, I eventually got the code working with vertexArrays (since the regular array was causing the exception due to unknown size of vertices).... after all this work I was expecting an improvement in performance but my frame rate is almost half what it was when rendering twice with immediate mode.... Maybe I'm doing something extra here? I managed to implement a std::vector collection like recommended:

        for(int i = 0; i < numTriangles; i++) {
            MD2Triangle* triangle = triangles + i;
            for(int j = 0; j < 3; j++) {
                MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
                MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
                Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
                Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
                if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
                    normal = Vec3f(0, 0, 1);
                }
    
    
                normals.push_back(normal[0]);
                normals.push_back(normal[1]);
                normals.push_back(normal[2]);
    
                MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
                textCoords.push_back(texCoord->texCoordX);
                textCoords.push_back(texCoord->texCoordY);
    
                vertices.push_back(pos[0]);
                vertices.push_back(pos[1]);
                vertices.push_back(pos[2]);
            }
    
        }
    
    
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_VERTEX_ARRAY);
    
        glNormalPointer(GL_FLOAT, 0, &normals[0]);
        glTexCoordPointer(2, GL_FLOAT, 0, &textCoords[0]); 
        glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
    
    
    
        glDrawArrays(GL_TRIANGLES, 0, vertices.size()/3);
    
    
        glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
    
        vertices.clear();
        textCoords.clear();
        normals.clear();
    

    Is there something extra that I am doing here? Cos this is really meant to be more efficient that glBegin()/End(), right?

    Thanks for your time and help!

  • First of all: You misunderstood glDrawElements. This function takes as its last parameter indices to array of vertices/normals/texture_coordinates (not array with vertices / normals.....) - this can be used for indexed geometry.

    Second of all: You misunderstood glNormalPointer / glVertexPointer / glTexCoordPointer. Its 3rd parameter is stride, which means stride in the whole array of vertices / normals / tex_coordinates. So its always 8*sizeof(float). And also its lasta parameter is pointer to first elements (vertex coordinate, texture coordinate, normal coordinate). So it should be for normals really indices, for textures &(indices[3]) (I think also indices + 3 should work) and for vertices &(indices[5]).

    And for your first problem - you should use glDrawArrays, if you don't want to use indexed geometry. And you should use it in this way: glDrawArrays(GL_TRIANGLES, 0, totalVertices/8) - here "totalVertices/8" is your real count of vertices - each vertex has 8 parts - 3 normal coordinates + 2 texture coordinates + 3 vertex coordinates.

    But I really don't understand how your Unhandled exception... can occur, when you use the same mechanism in first case and there it's working properly.

    BTW: And this is not VBO. These are called vertex arrays - geometry data is transfered from CPU side to GPU side each time you call glDrawArrays. If you want to use VBOs (geometry is stored in GPU memory), you can try this tutorial. But what I have understood, you are doing some animation or interpolation (?) - you are using frame1 and frame2 and frac variable. So you can use vertex arrays of VBOs with some "streamed" flag - this means the data will be changed every frame (specified once and used once). –

Tags
c++ opengl vertex-arrays
Related questions and answers
  • &lt; numTriangles; i++) { MD2Triangle* triangle = triangles + i; for(int j = 0; j &lt; 3; j++) { MD2Vertex* v1 = frame1-&gt;vertices + triangle-&gt;vertices[j... = triangles + i; for(int j = 0; j &lt; 3; j++) { MD2Vertex* v1 = frame1-&gt;vertices + triangle-&gt;vertices[j]; MD2Vertex* v2 = frame2-&gt;vertices + triangle-&gt;vertices[j...); glEnableClientState(GL_VERTEX_ARRAY); // Point them to the objects arrays if (Objects[i].textured) glTexCoordPointer(2, GL_FLOAT, 0, Objects[i].TexCoords

  • ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_COLOR_ARRAY ); glVertexPointer( 3, GL_FLOAT, sizeof(CustomVertex), ((char*)NULL + 0) ); glTexCoordPointer(3, GL_FLOAT, sizeof..._TRIANGLES, m_nNumIndices, GL_UNSIGNED_INT, ((char*)NULL + 0) ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY...: float m_Position[3]; // x, y, z // offset 0, size = 3*sizeof(float) float m_TexCoords[2]; // u, v // offset 3*sizeof(float), size = 2*sizeof(float) float m_Normal[3

  • I'm trying to load MD2 models (stolen from Cube) and my loader seems to be loading the models fine, but I can't say the same for the drawing of the model. Here's my code: typedef float vec3_t[3... char index_normal; }; typedef short md2_textcoord_t[2]; struct md2_frame_t { float scale[3]; vec3_t translate; char name[16]; md2_vertex_t vertices[1]; // First vertex of this frame..._Commands, m_MD2Header.num_glcommands * sizeof(int)); // Read all the data. for(int i = 0; i &lt; m_MD2Header.num_frames; ++i) { md2_frame_t* Frame = (md2_frame_t*)&amp;Buffer

  • (&amp;dsvd, sizeof(dsvd)); dsvd.Format = DXGI_FORMAT_D32_FLOAT; // one 32-bit float per pixel dsvd.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; // depth buffer is a 2D texture device-&gt... memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy the vertices to the buffer pBuffer-&gt;Unmap(); // create the index buffer out of DWORDs DWORD OurIndices[] = { 0, 1, 2, // side 1... pBuffer-&gt;Map(D3D10_MAP_WRITE_DISCARD, 0, &amp;pVoid); // map the vertex buffer memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy the vertices to the buffer pBuffer-&gt;Unmap

  • --; cspace++;}} for(int s= 0; s &lt;sspace; s++) buff[buff.size()-1].push_back(' '); // cwall2 //if(cwall2!= 0){ // if(cwall2&gt;0... every 3 or 4 X's down in the wall... I hope this is enough explination, Thanks for any Help, and LOOK AT PREVIOUS POST ABOUT COLLISION DETECTION FOR MORE SPECIFIC FUNCTION PROBLEMS otherwise, heres all the code: Thanks again! #include &lt;iostream> #include &lt;time.h&gt; // or "ctime" #include &lt;stdio.h&gt; // for #include &lt;cstdlib> // Windows stuff #include &lt;Windows.h&gt

  • () == 3) //should have all the info, or, same as above, its not worth the time { tempFace.vertexIndexes[1] = atoi(faceToken[0].c_str()) - 1... for learning). I can load all the data into std::vectors but I don't know how to put it into an array of vertices and indices, so it's rendering wrong. Here's how it turns out with no culling... structure contains the the indices of the vertices positions, normals, and texture coords. I haven't implemented texture coords yet, though. struct FaceDefinition { int vertexIndexes[3]; int

  • is identified, so that's all good. I'm writing the game in C++ with OpenGl/GLFW The drawing function is: int win_width; int win_height; glfwGetWindowSize(&amp;win_width, &amp;win_height); float win...++) { glBegin(GL_POLYGON); for(int c = 0; c &lt; (int)groups[a].faces[b].vertices.size(); c++) { vertexIndex = groups[a].faces[b].vertices[c]; glVertex3d... a = 0; a &lt; (int)groups.size(); a++) { if(groups[a].type == "prop") { //Code for rotation glPopMatrix(); glPushMatrix(); float x,y,z; x = y = z = 0; int

  • ); glBindFramebuffer(GL_FRAMEBUFFER, 0); } Here is my drawing box code, which just takes a transformation matrix and calls the appropriate functions. The current values of P is a projection matrix...;MVP[0]); } glBindVertexArray(vaoID); glDrawElements(GL_TRIANGLES, sizeof(cube.polygon)/sizeof(cube.polygon[0]), GL_UNSIGNED_INT, 0); } void drawStaticBox() { Matrix4 M(1... wrong in my frame buffer set up code, or elsewhere. But I can't see what. The FBO is set up through the following function: unsigned int fbo_id; unsigned int depth_buffer; int m_FBOWidth, m_FBOHeight

  • ).getHeightImage(); int widthMap = 40 + offsetX/32; int heigthMap = 23; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glBindTexture( GL_TEXTURE_2D, tilesetList.at(indexTileset).getTexture() ); for (int i = 0; i &lt; heigthMap; i++) { int startX = offsetX/32..._FLOAT, 0, texVerts); glDrawArrays(GL_QUADS, 0, 4); startX++; } } glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE

Data information