Particle Vertex Array

Apprentice
Posts: 9
Joined: 2010.02
Post: #1
Hi,

how i can render particles, with Vertex arrays. I have this simple structur

Code:
typedef struct _particle
{    
    float        finalColor[4];
    float        vertices[12];
.
.
.
}Particle;

init
Code:
_particles[i].vertices[0] =_particles[i].position[0]-(_particles[i].size/2);
_particles[i].vertices[1] =_particles[i].position[1]-(_particles[i].size/2);
_particles[i].vertices[2] =_particles[i].position[2];
        
_particles[i].vertices[3] =_particles[i].position[0]+(_particles[i].size/2);
_particles[i].vertices[4] =_particles[i].position[1]-(_particles[i].size/2);
_particles[i].vertices[5] =_particles[i].position[2];
        
_particles[i].vertices[6] =_particles[i].position[0]+(_particles[i].size/2);
_particles[i].vertices[7] =_particles[i].position[1]+(_particles[i].size/2);
_particles[i].vertices[8] =_particles[i].position[2];
        
_particles[i].vertices[9] =_particles[i].position[0]-(_particles[i].size/2);
_particles[i].vertices[10] =_particles[i].position[1]+(_particles[i].size/2);
_particles[i].vertices[11] =_particles[i].position[2];

and i like to render the particles like this:
Code:
glVertexPointer(3, GL_FLOAT, sizeof(Particle), &_particles[0].vertices);
glDrawArrays(GL_QUADS, 0, NUM_PARTICLES);

but, that seems to be wrong. Someone an idea?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #2
Looks like there are two problems here:
  • The stride parameter to glVertexPointer is the number of bytes from the end of one vertex to the beginning of the next, as opposed to the number of bytes from the beginning of one vertex to the beginning of the next. This tripped me up, too. You'll want something like sizeof(struct _particle) - sizeof(_particles[0].vertices).
  • ...However, this won't actually work, because the stride specifies the bytes between vertices, as opposed to the space between primitives. You may need to reorganize your data so that the space between each set of vertex coordinates is consistent. As it's currently set up, you have a 16-byte chunk between each quad, but the vertices in the quad itself are tightly packed.
Quote this message in a reply
Apprentice
Posts: 9
Joined: 2010.02
Post: #3
Thanks,
but how can i do this.

Thats why i ask.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #4
You'll need to model the data in your application in some way that allows lists of vertices to either be contiguous across the entire array you're drawing, or to have uniform byte spacing between each vertex across the entire array. How you accomplish this is really up to you; do whatever makes the most sense to fit into your current data model given the above constraints.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #5
Here's how I arranged my data, for a foliage system ( a specialized particle system ).

Code:
struct foliage_vertex
{
    static const int INTERLEAVED_FORMAT = GL_T2F_C3F_V3F;
    
    inline foliage_vertex( void ) {}
    
    inline foliage_vertex( const foliage_vertex &c ):
        texcoord( c.texcoord ),
        color( c.color ),
        position( c.position )
    {}

    inline foliage_vertex( const vec2 &tc, const vec3 &c, const vec3 &p ):
        texcoord( tc ),
        color( c ),
        position( p )
    {}
    
    inline foliage_vertex &operator = ( const foliage_vertex &c )
    {
        texcoord = c.texcoord;
        color = c.color;
        position = c.position;
        return *this;
    }
    
    vec2 texcoord;
    vec3 color, position;
};

struct foliage_quad {
    foliage_vertex a,b,c,d;
    
    inline foliage_quad( void ) {}
    inline foliage_quad( const foliage_quad &f ):
        a( f.a ),
        b( f.b ),
        c( f.c ),
        d( f.d )
    {}

    inline foliage_quad &operator = ( const foliage_quad &f )
    {
        a = f.a;
        b = f.b;
        c = f.c;
        d = f.d;
        return *this;
    }
    
};

... later

std::vector< foliage_quad > _foliage;

And to submit it to GL:
Code:
glInterleavedArrays( foliage_vertex::INTERLEAVED_FORMAT, 0, &(_foliage.front()) );
glDrawArrays( GL_QUADS, 0, _numQuads * 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );

Works for me!

Note: I'm billboarding in a vertex shader, so in principle I could use a VBO instead of a vertex array. BUT: I'm periodically depth-sorting the vertices, so I need to stream them. I could probably switch to a streaming or write-only vbo-format, but my foliage system allocation strategy is a little rough, and I don't want to blow out my vram.
Quote this message in a reply
Apprentice
Posts: 9
Joined: 2008.01
Post: #6
ThemsAllTook Wrote:Looks like there are two problems here:
  • The stride parameter to glVertexPointer is the number of bytes from the end of one vertex to the beginning of the next, as opposed to the number of bytes from the beginning of one vertex to the beginning of the next. This tripped me up, too. You'll want something like sizeof(struct _particle) - sizeof(_particles[0].vertices).

Err, are you sure about that? I just wrote some testing code to render a VBO and the stride is the number of byte from the start of a vertice to the next.

For example, if you have
Code:
// FIXME: dirty testing code
    size_t float_count = vertex_count * (3 + 3 + 2 + 2 + 1);
    buf_len = sizeof(GLfloat) * float_count;
    buf = malloc(buf_len);

    uint32_t i;
    for(i = 0; !feof(fd) && i < float_count;) {
        // FIXME: fscanf is dirty, only for testing, move to binary when working.
        vec3 v;
        // pos
        fscanf(fd, "%f %f %f\n", &v.f[0], &v.f[1], &v.f[2]);
        v = v_div3f(v, 100000);
        buf[i++] = v.f[0];
        buf[i++] = v.f[1];
        buf[i++] = v.f[2];

        // norm
        fscanf(fd, "%f %f %f\n", &v.f[0], &v.f[1], &v.f[2]);
        v = v_div3f(v, 100000);
        buf[i++] = v.f[0];
        buf[i++] = v.f[1];
        buf[i++] = v.f[2];

        // uv0
        fscanf(fd, "%f %f\n", &v.f[0], &v.f[1]);
        v = v_div3f(v, 100000);
        buf[i++] = v.f[0];
        buf[i++] = v.f[1];

        // uv1
        fscanf(fd, "%f %f\n", &v.f[0], &v.f[1]);
        v = v_div3f(v, 100000);
        buf[i++] = v.f[0];
        buf[i++] = v.f[1];

        // flags
        fscanf(fd, "%f\n", &v.f[0]);
        buf[i++] = v.f[0];
}


You will do something like:

Code:
#define glOffsetf(_x) ((const GLvoid *)(_x * sizeof(GLfloat)))
    #define glStridef(_x) (_x * sizeof(GLfloat))


    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    
    glVertexPointer(3, GL_FLOAT, glStridef(11), glOffsetf(0));    
    glNormalPointer(GL_FLOAT, glStridef(11), glOffsetf(3));

    glClientActiveTexture(GL_TEXTURE0);
    glTexCoordPointer(2, GL_FLOAT, glStridef(11), glOffsetf(6));

    glClientActiveTexture(GL_TEXTURE1);
    glTexCoordPointer(2, GL_FLOAT, glStridef(11), glOffsetf(8));

    glEnableVertexAttribArray(attrib_loc);
    glVertexAttribPointer(attrib_loc, 1, GL_FLOAT, GL_FALSE, glStridef(11), glOffsetf(10));

    glDrawArrays(GL_TRIANGLES, 0, vertex_count);

Note that the stride is always 11 * sizeof(GLfloat).

This code is working properly (even if it's dirty).
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #7
kuon is correct; stride is either 0 ("tightly packed") or number of bytes from the beginning of one vertex to the beginning of the next.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #8
Hmm, my mistake. The man page isn't worded as clearly as it could be...
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #9
ThemsAllTook Wrote:The man page isn't worded as clearly as it could be...

... Nice save!
Quote this message in a reply
Apprentice
Posts: 9
Joined: 2010.02
Post: #10
Thanks for suggestions
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Vertex shader particle billboarding question TomorrowPlusX 3 5,378 Sep 15, 2008 06:46 AM
Last Post: TomorrowPlusX
  Vertex Array &amp; Interleaved Array troubles TomorrowPlusX 5 5,310 Nov 17, 2007 09:59 AM
Last Post: TomorrowPlusX
  Vertex Array Range bonanza 3 3,637 Jun 19, 2007 12:42 PM
Last Post: OneSadCookie
  Compiled vertex array problem Frank C. 1 2,356 Feb 7, 2006 10:06 PM
Last Post: Frogblast
  Quad Vertex Array Woes WakingJohn 1 2,271 Apr 9, 2005 07:55 PM
Last Post: WakingJohn