Jump to content
  • Advertisement
Sign in to follow this  
SFCBias

Cannot Understand or get VBOs working

This topic is 2810 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im sure people are getting quite tired of seeing posts about VBOs by now. And since this is my first post, it may not be priority. However,

I've searched these and several other forums have done about a weeks worth or research on this but i still cannot get my VBO's to work. SO I decided to post my code and find out where im going wrong.

I've had the impression that it may be the Vertex stucture or simply how im passing the data, and so i've tried different methods and tweaked parameters here and there but still not luck.

Class VertexBufferObject (Based off of CVertexBufferObject class found in this post http://www.gamedev.net/community/forums/topic.asp?topic_id=424778 with additions)

/*
* SFC_VertexBufferObject.cpp
*
* Created on: Nov 8, 2010
* Author: bryce
*/


#include "SFC_VertexBufferObject.h"
#include "SFC_LogManager.h"

namespace SFC
{

VertexBufferObject::VertexBufferObject() :
mVBOData(NULL), mVBODataSize(0), mAvailableSize(0), mVBOID(0)

{
glGenBuffersARB(1, &mVBOID);
}

VertexBufferObject::~VertexBufferObject()
{
glDeleteBuffersARB(1, &mVBOID);
}

void VertexBufferObject::Bind()
{
glBindBufferARB(GL_ARRAY_BUFFER, mVBOID);
}

void VertexBufferObject::disableVBOs()
{
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void VertexBufferObject::setData(int size, void *data)
{
Bind();

glBufferDatARB(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
mVBOData = data;
mVBODataSize = size;

if (data == NULL)
mAvailableSize = size;

#ifdef _DEBUG
char str[256];
sprintf(str, "Allocating VBO Memory. Size: %d", size);
LogManager::getSingletonPtr()->logMessage(str);
#endif

}

void VertexBufferObject::setData(int size, void *data, GLenum usage,
GLenum target)
{
Bind();

glBufferDataARB(target, size, data, usage);

mVBOData = data;
mVBODataSize = size;

if (data == 0)
mAvailableSize = size;

#ifdef _DEBUG
char str[256];
sprintf(str, "Allocating VBO Memory. Size: %d", size);
LogManager::getSingletonPtr()->logMessage(str);
#endif

}

void VertexBufferObject::setSubData(int size, int offset, const void *data)
{
Bind();

glBufferSubDataARB(GL_ARRAY_BUFFER, offset, size, data);
mAvailableSize -= size;


#ifdef _DEBUG
char str[256];
sprintf(str,
"Filling VBO Memory. Size: %d\nAvailable Buffer memory: %d",
size, mAvailableSize);
LogManager::getSingletonPtr()->logMessage(str);
#endif

}

void VertexBufferObject::setSubData(int size, int offset, const void *data,
GLenum target)
{
Bind();
glBufferSubDataARB(target, offset, size, data);
mAvailableSize -= size;

#ifdef _DEBUG
char str[256];
sprintf(str,
"Filling VBO Memory. Size: %d\nAvailable Buffer memory: %d",
size, mAvailableSize);
LogManager::getSingletonPtr()->logMessage(str);
#endif

}
void *VertexBufferObject::getVBOData() const
{
return mVBOData;
}

unsigned int VertexBufferObject::getVBODataSize() const
{
return mVBODataSize;
}

unsigned int VertexBufferObject::getVBOID() const
{
return mVBOID;
}
}




Mesh.cpp
[source ]
/*
* SFC_Mesh.cpp
*
* Created on: Oct 27, 2010
* Author: bryce
*/


#include "SFC_Mesh.h"
#include "SFC_StdAfx.h"
#include "SFC_Point2D.h"
#include "SFC_Point3D.h"
#include "SFC_VertexBufferManager.h"
#include "SFC_VertexBufferObject.h"

namespace SFC
{
/*

// VBO Extension Function Pointers
PFNGLGENBUFFERSARBPROC glGenBuffersARB; // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC glBindBufferARB; // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC glBufferDataARB; // VBO Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB; // VBO Deletion Procedure

*/


Mesh::Mesh()
{
// Set Pointers To NULL
mVertices = NULL;
mVertexCount = 0;
}

Mesh::~Mesh()
{
// Delete Data
if (mVertices)
delete[] mVertices;
mVertices = NULL;

if (mSubMeshes)
{
for (int i = 0; i < mSubMeshCount; i++)
{
free(mSubMeshes.mIndexArray);
}
free(mSubMeshes);
}
}

void Mesh::loadMesh(const std::string& meshName)
{
int vertexCount;
int subMeshCount;
char outPathName[2048] = "";
FILE* file;

strcpy(outPathName, meshName.c_str());

file = fopen(outPathName, "rb");

if (file == NULL)
{
std::string str;
str.assign("Cannot locate file named: ").append(meshName);
SFC_EXCEPT(E_FileNotFound,str);
}

// read all of the vertices's, normal and UV
fscanf(file, "%s %d/n", outPathName, &vertexCount);
mVertexCount = mNormalCount = vertexCount;
mVertices = new Vertex[mVertexCount]; // Allocate Vertex Data
//GLfloat* mTestVert = (GLfloat*)malloc(3 * mVertexCount * sizeof(float));
for (int i = 0; i < vertexCount; i++)
{
fscanf(file, "%f %f %f ", &mVertices.positions[0],
&mVertices.positions[1], &mVertices.positions[2]);
fscanf(file, "%f %f %f ", &mVertices.normal[0],
&mVertices.normal[1], &mVertices.normal[2]);
fscanf(file, "%f %f\n", &mVertices.tex[0], &mVertices.tex[1]);
}

// read all of the mesh segments,
fscanf(file, "%s %d/n", outPathName, &subMeshCount);
mSubMeshCount = subMeshCount;
mSubMeshes = new SubMesh[mSubMeshCount];
for (int i = 0; i < subMeshCount; i++)
{
int indexCount;
char texName[256];
fscanf(file, "%s %s/n", outPathName, texName);
fscanf(file, "%s %d/n", outPathName, &indexCount);

// load the texture for this submesh
//mSubMeshes.mTextureHandle = LoadTexture(texName);
mSubMeshes.mIndexCount = indexCount;
mSubMeshes.mIndexArray = new unsigned short[indexCount];
for (int j = 0; j < indexCount; j++)
{
int index;
fscanf(file, "%d ", &index);
mSubMeshes.mIndexArray[j] = (unsigned short) index;
}
fscanf(file, "\n");
}

// close file after reading
fclose(file);

}

void printArray(float* array, int arraySize)
{
for (int i = 0; i < arraySize; i++)
std::cout << array[i * 3] << " " << array[i * 3 + 1] << " "
<< array[i * 3 + 2] << std::endl;
}

void Mesh::BuildVBOs()
{

//printArray(&mVertices[0].positions[0].fX,mVertexCount);
VertexBufferManager *vbm = VertexBufferManager::getSingletonPtr();
mVBO0 = vbm->createVBO();
mVBO0->setData(sizeof(Vertex) * mVertexCount, NULL);
mVBO0->setSubData(sizeof(Vertex) * mVertexCount, 0, mVertices);
mVBO1 = vbm->createVBO();
mVBO1->setData(sizeof(unsigned short) * mSubMeshes[0].mIndexCount,
mSubMeshes[0].mIndexArray, GL_STATIC_DRAW,
GL_ELEMENT_ARRAY_BUFFER);
//mVBO->setSubData(mNormalCount, 0, &mNormal[0].fX);

}
}





This is where it's rendered
Entity.cpp
[source ]
bool Entity::update(float timeSinceLastFrame)
{

mMesh->mVBO0->Bind();
mMesh->mVBO1->Bind();
// Set the state of what we are drawing (I don't think order matters here, but I like to do it in the same
// order I set the pointers
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

// Resetup our pointers. This doesn't reinitialise any data, only how we walk through it
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(20));
// glColorPointer(4, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(32));
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));

// Actually do our drawing, parameters are Primative (Triangles, Quads, Triangle Fans etc), Elements to
// draw, Type of each element, Start Offset
glDrawElements(GL_TRIANGLES, mMesh->mSubMeshes->mIndexCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

// Disable our client state back to normal drawing
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
// it is good idea to release VBOs with ID 0 after use.
// Once bound with 0, all pointers in gl*Pointer() behave as real
// pointer, so, normal vertex array operations are re-activated
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

return true;
}





And finally my Vertex Structure
[source ]	typedef struct //Struct represents ONE VERTEX in a polygon or triangle
{
GLfloat positions[3];
GLfloat tex[2];
GLfloat normal[3];
GLfloat color[4];
GLubyte padding[16];
} Vertex;




[Edited by - SFCBias on November 11, 2010 1:18:58 PM]

Share this post


Link to post
Share on other sites
Advertisement
Maybe i'll look at it later and help you out. But for now, make a single function called outputDebugMessage(string message), and put a single #ifdef _DEBUG in to either output the string or not. That way you dont have ifdef's everywhere.

Share this post


Link to post
Share on other sites
The first thing I notice is that you're binding both data and indices to GL_ARRAY_BUFFER, when you should be binding your index to GL_ELEMENT_ARRAY_BUFFER (see the Bind()) function. This will definitely break your code, though I don't know if that's the only thing wrong.


Also please edit your post and place 'source' tags around your code, it creates nice formatting.


int x = 0+1;


Share this post


Link to post
Share on other sites
Quote:
Original post by karwosts
The first thing I notice is that you're binding both data and indices to GL_ARRAY_BUFFER, when you should be binding your index to GL_ELEMENT_ARRAY_BUFFER (see the Bind()) function. This will definitely break your code, though I don't know if that's the only thing wrong.


Also please edit your post and place 'source' tags around your code, it creates nice formatting.

*** Source Snippet Removed ***


Sorry im used the the VB tags

Share this post


Link to post
Share on other sites
hi:

I look at your code and i think i have spotted your bug.

In your Bind function, you always bind GL_ARRAY_BUFFER, but you need to bind your face indices with GL_ARRAY_ELEMENT_BUFFER imo

PS: next time, give an explanation of what errors are you getting, in order to help us to spot the error

Share this post


Link to post
Share on other sites
Thank you but that was not the problem. I just recently made that change but before I already was binding to GL_ELEMENT_ARRAY_BUFFER. Also I'm getting no errors, only getting a blank screen that is not rendering any triangles. But i have made the change you said.

Share this post


Link to post
Share on other sites
Well it certainly was 'a' problem.

Are you checking for opengl errors (glGetError)? I know you said you're getting no errors, but I don't know if you are checking opengl errors or not.

Are you certain your mesh data is correct? Can you try starting with just a single triangle?

Also if you made the fix that was suggested, can you keep your original post up to date with your most current code? Nobody can tell if you fixed it the right way, and it will save everyone else from noticing the same thing.

Share this post


Link to post
Share on other sites
I very well was getting a GL_INVALID_OPERATION error after calling


mVBO1->setData(sizeof(unsigned short) * mSubMeshes[0].mIndexCount,
mSubMeshes[0].mIndexArray, GL_STATIC_DRAW,
GL_ELEMENT_ARRAY_BUFFER);

Share this post


Link to post
Share on other sites
Is it failing on glBindBuffer or glBufferData? Double check all your variables in the debugger (vbo buffer id, number of indices, things like that).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!