How can I create a dynamic vertex array with C/C++?
I need to use DrawArray or DrawRangeElements for a varied number of vertices. I want to add/remove any number of vertices per frame to the array as needed.
I’ll need several arrays for different states, but I’m trying to stay simple for now. (Isn’t this what some engines do ? )
So far I found the C++ “placement new” but no good example of a dynamic vertex array.
But is it ok to realloc() a lot ? I read it uses malloc() to resize… so it might fragment the memory and eventually crash. I need to change the vertex/color/texture coords of the array as the program runs, per frame if possible.
I want to store up vertices and use a single call to DrawArray() functions to render it. I’m suprised there are no examples of this technique… seems to be what the commands are made for.
Use realloc in larger increments, and don’t shrink it.
E.g.:
const int increment=64; // you may want to experiment with this value
vertex *buffer=NULL;
int allocated=0;
int used=0;
// returns pointer to vertex where you can store your data - NULL if failed to allocate
vertex *addvertex()
{
vertex *newbuffer;
vertex *newvertex;
if(used==allocated) { // buffer full or no buffer
newbuffer = (vertex *)realloc(buffer,sizeof(vertex)*(allocated + increment);
if(newbuffer) {
buffer = newbuffer;
allocated+=increment;
}
}
if(used<allocated) {
newvertex = buffer+used;
used++;
return newvertex;
}
return NULL;
}
// reset the vertex pointer to the first in the array
resetbuffer()
{
used=0;
}
This way, you keep the number of reallocations and therefore fragmentation and expensive copy operations down, while remaining flexible w.r.t. the maximum number of vertices.
Of course, “malloc-wise” it would be even better to allocate the buffer in its entirety if you know the maximum size tat will be used.
The only thing this does is it allows you to have a buffer large enough to dump your vertex array into.
When you want to fill the vertex array, just resetbuffer and use the addvertex function on every vertex you want to send to the array.
Finally, the number of elements in the vertexpointer call would be “used”.
But it is a throwaway buffer in the sense that you have to fill it everytime.
If you want to allocate “static” vertex arrays (e.g. for every mesh one vertex array) you don’t really need realloc at all.
What array can I use for DrawArray()? I assumed “buffer” and it draws, but I’m not sure if that’s right. Do I free() “buffer” ?
I guess I can malloc a big buffer as long as I can change the vertex values during runtime. But most vertex array demos I’ve seen so far seem to use static arrays, and I need some non-static ones
Only free the buffer when you’re completely sick of rendering - in other words, when you’re ending the program, or loading up another game level or something.
If you “reset” the buffer before you fill it, it does not normally have to reallocate anything once it has grown to the necessary size.
The pointer you supply to OpenGL depends on the definition of the vertex. I kept that out of it because I don’t know what you’re trying to do per vertex.
But suppose you have a vertex structure as follows:
Ok I’m getting there… Yes I call reset() and it’s steady memory wise. I’m not sure what you mean by stride, are you talking about interleaving ?
I’m not going for anything fancy here, not even normals. Just x,y,z, s,t, and colors…
Could an interleaved array work best?
I’m trying for a particle system if anyone is curious.
I guess I should hack at things before asking from now on ; / I think it’s working right, it looks the same but it’s hard to be sure with my current test app.
I dont quite understand how I should assign values to the new vertives, or render vertices with this technique. Where do I put the returned vertices? Do I need another buffer?
resetbuffer();
while( i_want_to_add_a_vertex ) {
newvertex = addvertex();
if(newvertex) {
newvertex->x= ...
newvertex->y= ...
etc.
}
...determine if i still want to add more vertices
}
glIndexPointer(INT,sizeof(vertex),&(buffer[0].color));
glTexCoordPointer(2,FLOAT,sizeof(vertex),&(buffer[0].s));
glVertexPointer(3,FLOAT,sizeof(vertex),&(buffer[0].x));
glDrawArrays(GL_TRIANGLES,0,used);
“newvertex” is a pointer to a vertex structure.
The addvertex function is a bit like new and malloc. It tells you where you may store the vertex data.
Have another look at my example code, please.
You should be doing something like:
newvertex = addvertex();
if(newvertex){
newvertex->x=tri->v[0].x;
newvertex->y=tri->v[0].y;
newvertex->z=tri->v[0].z;
// etc.
}
// repeat for the other vertices
BTW: newvertex is only used by your RenderTri function, so make it local to that function.
Thank you T101 ! I was thrown off by the “newvertex” local to addvertex(). That and I was feeding each triangle the same coordinate values, so I couldn’t see it was actually drawing many triangles.