Jump to content
  • Advertisement
Sign in to follow this  
Mantear

Using glDrawRangeElements with std::vector

This topic is 4870 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

I'm trying to use a std::vector to hold my vertex data in my models. I have a Vertex object which contains vertex, color, normal, and texcoord information. I make a vector of those Vertex objects. I bind the vertex data by doing:
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &(((Vertex *) 0)->m_Coordinate));
I then try to draw a quad using:
glDrawRangeElements(GL_QUADS, 0, m_Quads.m_VertexIndex.size(), m_Quads.m_VertexIndex.size(), GL_UNSIGNED_INT, NULL);
I end up getting an "Unhandled exception in Program.exe (ATIOGLXX.DLL): 0xC0000005: Access Violation." All the other code, generating the VBOs, etc, I'm using from a version that's working fine. The only difference is how I'm storing and trying to use my data, so I'm confident that my problem resides somewhere in those 2 lines.

Share this post


Link to post
Share on other sites
Advertisement
&(((Vertex *) 0)->m_Coordinate) obtains the offset into the Vertex class object where m_Coordinates exists (which contains the x, y, z coordinates of the vertex). According to the documentation, the parameters for glVertexPointer are:

size
The number of coordinates per vertex. The value of size must be 2, 3, or 4.
type
The data type of each coordinate in the array using the following symbolic constants: GL_SHORT, GL_INT, GL_FLOAT, and GL_DOUBLE.
stride
The byte offset between consecutive vertices. When stride is zero, the vertices are tightly packed in the array.
pointer
A pointer to the first coordinate of the first vertex in the array.

So 3 for the size (3 coordinates), GL_FLOAT for the type (x, y, and z are floats), sizeof(Vertex) for the stride, and &(((Vertex *) 0)->m_Coordinate) provides the offset into a Vertex object, pointing to the start of the data. I'm not 100% sure as to how that last parameter works, since I got the code snippet from someone else doing the same thing, but it does seem to be providing the correct value. In my current case, it has a result of 4, meaning a 4 byte offset into the Vertex object.

Share this post


Link to post
Share on other sites
Yes, the last parameter looks OK. I'm not sure what the standard would have to say to it (come to that I'm not even sure where I'd look), but it's basically just offsetof(Vertex, m_Coordinate). Since VBOs use an offset into the currently bound buffer this is perfectly valid.

I'd be more suspicious of the glDrawRangeElements call, particularly the end parameter. I assume you've set up your GL_ELEMENT_ARRAY_BUFFER correctly and bound it? With your start and end parameters as they are you're stating that for every element in your GL_ELEMENT_ARRAY_BUFFER (element >= 0 && element <= m_Quads.m_VertexIndex.size()), which is probably true but only because there tend to be as many or more indicies than vertices (otherwise you have unused vertices). Best to double check anyway.

Enigma

Share this post


Link to post
Share on other sites
The last argument to glVertexPointer is the address of the beginning of the index information of the vertex array that you're passing to GL. It's not an offset. Right now you're passing 0x00000004 as the start of the index information, which GL will try to read, generating an access violation as 0x00000004 is a protected memory location.

Share this post


Link to post
Share on other sites
Only for Vertex Arrays. Vertex Buffer Objects "overload" the functions allowing you to specify the offset from the start of the currently bound buffer. From the VBO spec (emphasis mine):
Quote:
Rendering commands ArrayElement, DrawArrays, DrawElements,
DrawRangeElements, MultiDrawArrays, and MultiDrawElements operate as
previously defined, except that data for enabled vertex, variant, and
attrib arrays are sourced from buffers if the array's buffer binding
is non-zero. When an array is sourced from a buffer object, the
pointer value of that array is used to compute an offset, in basic
machine units, into the data store of the buffer object
. This offset
is computed by subtracting a null pointer from the pointer value,
where both pointers are treated as pointers to basic machine units.

And from the examples at the end of the spec:
Quote:
Convenient macro definition for specifying buffer offsets:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
// ...
VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0));
ColorPointer(4, UNSIGNED_BYTE, 0, BUFFER_OFFSET(256));

Enigma

Share this post


Link to post
Share on other sites
Quote:
Original post by EnigmaI'd be more suspicious of the glDrawRangeElements call, particularly the end parameter. I assume you've set up your GL_ELEMENT_ARRAY_BUFFER correctly and bound it? With your start and end parameters as they are you're stating that for every element in your GL_ELEMENT_ARRAY_BUFFER (element >= 0 && element <= m_Quads.m_VertexIndex.size()), which is probably true but only because there tend to be as many or more indicies than vertices (otherwise you have unused vertices).


I'm generating my VBOs using:
glGenBuffersARB(1, &m_CoordinateVboName);
glBindBufferARB(GL_ARRAY_BUFFER, m_CoordinateVboName);
glBufferDataARB(GL_ARRAY_BUFFER, m_Vertices.size() * 3 * sizeof(float), &m_Vertices[0], GL_DYNAMIC_DRAW);

glGenBuffersARB(1, &m_Quads.m_VertexIndexVboName);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, m_Quads.m_VertexIndexVboName);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, m_Quads.m_VertexIndex.size() * sizeof(unsigned int), &m_Quads.m_VertexIndex[0], GL_DYNAMIC_DRAW);
When I go to draw, I use:
glBindBufferARB(GL_ARRAY_BUFFER, m_CoordinateVboName);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &(((Vertex *) 0)->m_Coordinate));

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, m_Quads.m_VertexIndexVboName);
glDrawRangeElements(GL_QUADS, 0, m_Quads.m_VertexIndex.size(), m_Quads.m_VertexIndex.size(), GL_UNSIGNED_INT, NULL);


Quote:
Right now you're passing 0x00000004 as the start of the index information, which GL will try to read, generating an access violation as 0x00000004 is a protected memory location.
Isn't this what I do anyways, when there isn't an offset? In my old version, I was simply using a plain old array. My offset was 0, so I had:
glVertexPointer(3, GL_FLOAT, 0, 0);
Now my offset is 4 bytes, so why shouldn't the 4th paramter be 4?

Share this post


Link to post
Share on other sites
glBufferDataARB(GL_ARRAY_BUFFER, m_Vertices.size() * 3 * sizeof(float), &m_Vertices[0], GL_DYNAMIC_DRAW);
...
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &(((Vertex *) 0)->m_Coordinate));


This look suspicious. Especially if &(((Vertex *) 0)->m_Coordinate)) is 4 like you say. What exactly are you storing in m_Vertices? I would probably have expected that first line to be:

glBufferDataARB(GL_ARRAY_BUFFER, m_Vertices.size() * sizeof(Vertex), &m_Vertices[0], GL_DYNAMIC_DRAW);

assuming m_Vertices stores Vertex objects (if so it would be useful to see a definition for Vertex).

The start and end parameters for glDrawRangeElements should be equivalent to:
unsigned int min = std::numeric_limits< unsigned int >::max();
unsigned int max = 0;
for (int i = 0; i < m_Quads.m_VertexIndex.size(); ++i)
{
min = std::min(min, m_Quads.m_VertexIndex);
max = std::max(max, m_Quads.m_VertexIndex);
}
glDrawRangeElements(..., min, max, ..., ..., ...);

Enigma

Share this post


Link to post
Share on other sites
Yes, your suggestion of changing the glBufferData function seems to be correct. However, I changed it but have the same error.

My Vertex class is as follows:

typedef struct
{
float X;
float Y;
float Z;
} sCoordinates;

typedef struct
{
unsigned char R;
unsigned char G;
unsigned char B;
unsigned char A;
} sColors;

typedef struct
{
float X;
float Y;
float Z;
} sNormals;

typedef struct
{
float U;
float V;
} sTexCoords;

class Vertex
{
public:

// Constructors and Destructors
Vertex(void) {}

~Vertex(void) {}


unsigned int m_TimesUsed;
sCoordinates m_Coordinate;
sColors m_Color;
sNormals m_Normal;
sTexCoords m_TexCoord;
};



My Polygon class, of which m_Quad is, contains a vector of unsigned ints, containing the vertex index values for all quads in the model.

I'll look into setting the proper start/end parameters once I get things drawing.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!