Re: Using STL vectors with VBOs and vertex arrays?



Army <earmbrust@xxxxxxxxxxxxx> wrote:

fungus wrote:

Army wrote:
\>>> Here's what I have currently:

glEnable(GL_VERTEX_ARRAY);
glGenBuffersARB(1, &bufferdata);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferdata);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
model.iVertexCount*3*sizeof(float), &model.fVertices,
GL_STATIC_DRAW_ARB);

...and as has been pointed out at least twice,
"&model.fVertices" is a pointer to the vector,
not a pointer to the data in the vector.


Also, "model.fVertices.size()*sizeof(cVertex)" is
much better then "model.iVertexCount*3*sizeof(float)",

a) Because it relieves you of the responsibility
of keeping iVertexCount accurate.

b) Because you can change cVertex without causing
new bugs.

When I attempt to access the variable as &model.fVertices[0] I get no
resulting image,

You most probably have other errors as well. Trust us, in your case
'&model.fVertices[0]' is correct and '&model.fVertices' is not.

not so with accessing it as &model.fVertices for some
reason even though it is the wrong information displayed. Thank you

Errors adding up I'd say.

The Standard C++ language defines something called 'undefined
behaviour'. When you have that (which you do), anything might happen,
including demons flying out of your nose ;-) My point being: it is pure
luck that your application displayed anything at all and did not just
crash.

for the information regarding iVertexCount, it seems to be working
perfectly. I've included much of the code below, in case someone can
pick out the specific problem causing this issue. (The wrong
information being displayed, or not being displayed at all)



class cVertex {
public:
float x, y, z;
};
class cNormal {
public:
float x, y, z;
};

class cColor {
public:
float r, g, b, a;
};

class cTextureCoord {
public:
float u, v, w;
};

class cFaceIndex {
public:
int a, b, c;
};

class cNormalIndex {
public:
int a, b, c;
};

class cTexCoordIndex {
public:
int a, b, c;
};

class cModelObject {
public:
char cName[128];
int iBegin, iSize;
};


class cModel {
public:
int iVertexCount, iNormalCount, iTextureCount, iFaceCount,
iObjectCount;
vector<cVertex> fVertices;
vector<cNormal> fNormals;
vector<cTextureCoord> fTexCoords;

vector <vector <unsigned int> > iFaceVertices;
vector <cNormalIndex> iFaceNormals;
vector <cTexCoordIndex> iFaceTexCoords;
vector <cModelObject> gObjects;
bool LoadFile(char* filename);
};






GLuint bufferdata;
int iVertexCount, iFaceCount; //total number of vertices
vector<cVertex> fVertices;
vector <vector <unsigned int> > iFaceVertices;

//generating and binding
glEnableClientState(GL_VERTEX_ARRAY);
glGenBuffersARB(1, &bufferdata);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferdata);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
model.fVertices.size()*sizeof(cVertex), &model.fVertices,

See above. It *must* be &model.fVertices [0]. If this does not work
either, then you have other errors that need to be fixed until you see
correct results.

Just an explanation why the above line of code is utterly wrong: A
vector is most likely a class containing pointers to the data, like so:

class vector
{
T* begin;
T* end;
T* last;
};

Now when you take the address of the vector, you are not getting the
pointer to your data (which would be 'begin'), but the address of it. So
you are telling OpenGL your floats are at a location, where something
completely different is stored.

GL_STATIC_DRAW_ARB);


//and then drawing:
glEnableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferdata);

Does bufferdata still hold the value it had when you created the
buffer? Just a thought, because it is not 100% clear from this code.

glVertexPointer( 3, GL_FLOAT, 0, &model.fVertices); //suffixing

Again. Never ever pass the address of a vector when array data is
expected.

with [0] on this and the next line (&model.iFaceVertices[0]) produces
no visible result
glDrawElements(GL_TRIANGLES, model.iFaceCount*3, GL_UNSIGNED_INT,
&model.iFaceVertices);


Same here again. 'model.iFaceVertices' is a vector of vectors, which
is why '&model.iFaceVertices' is the address of the vector of vectors
and '&model.iFaceVertices [0]' is the address of the first vector. Do
not do that. Tho I do not understand why you have a vector of vectors,
this should probably be:

glDrawElements(GL_TRIANGLES, model.iFaceCount*3, GL_UNSIGNED_INT,
&model.iFaceVertices [0] [0]);

Sadly, those OpenGL functions take a void*, which wrecks all
type-safety and leads to obviously gross errors. Here is an idea to get
the type-safety back: Instead of passing the vector data directly,
create a temporary pointer to the data, which you pass to the function.
The compiler will optimize the temporary away. Do that for *every* call
where you pass an array. So instead of


glVertexPointer (3, GL_FLOAT, 0, &model.fVertices [0]);

glDrawElements (GL_TRIANGLES, model.iFaceCount*3, GL_UNSIGNED_INT,
&model.iFaceVertices [0] [0]);


you will write:


float* pv = &model.fVertices [0].x; // note the .x!
glVertexPointer (3, GL_FLOAT, 0, pv);

unsigned int* pf = &model.iFaceVertices [0] [0];
glDrawElements (GL_TRIANGLES, model.iFaceCount * 3, GL_UNSIGNED_INT,
pf);


And if you get the conversion from vector to raw array data wrong,
the compiler will tell you.

hth
--
jb

(reply address in rot13, unscramble first)


.



Relevant Pages