Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


glDrawArrays causing Access Violations


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
21 replies to this topic

#1 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 31 August 2001 - 11:35 AM

I have a "terrain" class with a "draw" method. I have the following protected member variables & pointers (that apply to this problem):
  
	unsigned int width, height;
	GLfloat ** verts;
	GLfloat ** texs;
  
...and in my constructor, I allocate memory like so:
  
		verts = new GLfloat * [width * 2];
		for(unsigned int i = 0; i < width * 2; i++)
		{
			verts[i] = new GLfloat[3];
		}

		texs = new GLfloat * [width * 2];
		for(i = 0; i < width * 2; i++)
		{
			texs[i] = new GLfloat[2];
		}
  
Later, in my draw() function, I do this:
  
		glVertexPointer  (3, GL_FLOAT, 0, verts);
		glTexCoordPointer(2, GL_FLOAT, 0, texs);
  
And then, later in the draw function, an access violation is produced at the following line of code:
  
glDrawArrays(GL_TRIANGLE_STRIP, 0, width * 2);
  
I figure I must be doing something wrong. Could anybody tell me what that thing is?

Sponsor:

#2 Null and Void   Moderators   -  Reputation: 1087

Like
Likes
Like

Posted 31 August 2001 - 11:47 AM

Don''t use 2D arrays, they won''t work as they''re not contiguous.

[Resist Windows XP''s Invasive Production Activation Technology!]

#3 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 31 August 2001 - 12:14 PM

I had a linear array of vertices, vertices being arrays of GLfloats. I thought I had remembered seeing it done this way, but you say that doesn't work, so I guess I must be remembering incorrectly. So I tried creating larger linear arrays that are three and two times as large, respectively, so that now, instead of my arrays working like this:


verts[0] = {x1, y1, z1};
verts[1] = {x2, y2, z2};
verts[2] = {x3, y3, z3};

etc...

...they now are supposed to work like this:


verts[0] = x1; verts[1] = y1; verts[2] = z1;
verts[3] = x2; verts[4] = y2; verts[5] = z2;
verts[6] = x3; verts[7] = y3; verts[8] = z3;


Except they don't work. I tried calling glVertexPointer with different arguments, but nothing I tried worked.

How SHOULD my vertex and texture coordinate arrays be set up, and how SHOULD I call the associated OpenGL functions?

Edited by - TerranFury on August 31, 2001 8:29:00 PM

#4 Null and Void   Moderators   -  Reputation: 1087

Like
Likes
Like

Posted 31 August 2001 - 12:26 PM

The rest of your code looks ok. I''ve only experimented with vertex arrays a little though, so I may be missing something. You may want to try GL_TRIANGLES or GL_QUADS as a test though.

[Resist Windows XP''s Invasive Production Activation Technology!]

#5 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 31 August 2001 - 12:43 PM

I''ve heard of something called glDrawElements, and that seems to be an alternative. But I don''t understand what the "indices" argument is supposed to be. Could I use that somehow instead of glDrawPointers, and, if so, how?

#6 zedzeek   Members   -  Reputation: 528

Like
Likes
Like

Posted 31 August 2001 - 12:56 PM

did u enable the vertex + texture coordinate arrays?

#7 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 31 August 2001 - 03:04 PM

Yes, both are and were enabled. And even if they weren''t, I doubt that would be the cause of the Access Violation. If they weren''t, all that would happen is the triangle strips wouldn''t be drawn.

#8 outRider   Members   -  Reputation: 852

Like
Likes
Like

Posted 31 August 2001 - 04:13 PM

Maybe your pointers are invalid, or you''re telling glDraw* to access something out of range with your arguments.

Set up a dummy array with a few values and try drawing that to see if its your code or something else.

As for the glDrawElements, you need to have indices to your verts to be able to use them. If you have any verts that are used by more than 1 triange you can use indices to cut down on the number of verts, so you only store the verts once and use indices, which saves 8 bytes for every use of that vert.

------------
- outRider -

#9 zedzeek   Members   -  Reputation: 528

Like
Likes
Like

Posted 31 August 2001 - 04:40 PM

sorry i meant the opposite to what i said :D
did u DISABLE the other arrays cause having them enabled with no valid data to point at will most likely cause an access voilation

#10 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 01 September 2001 - 04:44 AM

Do you have a short example of the use of glDrawElements I could see?

#11 MENTAL   Members   -  Reputation: 383

Like
Likes
Like

Posted 01 September 2001 - 05:21 AM

glDrawElements example. please note that i''m trying to remember this from memory, so dont expect it to be 100% accurate.

  
struct VERTEX
{
GLfloat Tex[2];
GLfloat Nor[3];
GLfloat Pos[3];
};

struct POLYGON
{
GLuint VertID[3];
};

struct MESH
{
VERTEX *Verts;
GLuint VertNum;

POLYGON *Polys;
GLuint PolyNum;
};

void DrawCrap (MESH *M)
{
glInterleavedArrays (GL_T2F_N3F_V3F, 0, M->Verts);
glDrawElements (GL_TRIANGLES, M->PolyNum, GL_UNSIGNED_INT, M->Polys);
}



I suppose you want an explaination for this too.

glInterleavedArrays


Passes a pointer to opengl containing "packed vertices" (i.e. all data in a single array, not multiple arrays).

GL_T2F_N3F_V3F
The vertex format - 2 Tex floats, 3 Normal floats, 3 Vertex floats, IN THAT ORDER (look at the definition of VERTEX)

0
This is the offset between the last vertex float and the next texcoord float. example:

  

struct VERTEX
{
GLfloat Tex[2];
GLfloat Nor[3];
GLfloat Pos[3];
GLfloat SomeRandomCrap;
};



"SomeRandomCrap" takes up 4 bytes of space, which means that there are 4 bytes between the end of the (opengl relevent) information for the current vertex and the next vertex.

because of this, we would pass "sizeof (GLfloat)" instead.

M->Verts
if you cant work this out then you need to be shot.

glDrawElements


Draws all the crap you just passed with glInterleavedArrays

GL_TRIANGLES
The type of data you want to draw.

M->PolyNum
Number of triangkes to draw.

GL_UNSIGNED_INT
How the data of incides is stored (aka M->Polys)

M->Polys
This is a list of indices (numbers used to access the array of vertices) that define which verts make up this polygon. For example, Polygon 1 might use verts 0, 1 and 2, so it''s indicies would be "0", "1", "2". Polygon 2 might use verts 1, 2 and 3, so it''s indicies would be "1", "2", "3".


if you still dont understand then bugger off, cuz this is a damn good explaination (shame the grammar and spelling arnt as good).


MENTAL

#12 MENTAL   Members   -  Reputation: 383

Like
Likes
Like

Posted 01 September 2001 - 05:25 AM

hmmm... just seen something else. ya know, usually trying to ACCESS protected areas in a class from outside would churn out an ACCESS VIOLATION.

just a thought.

MENTAL

#13 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 01 September 2001 - 05:33 AM

Thanks a lot MENTAL, that''s the best explanation I could have hoped for!

#14 MENTAL   Members   -  Reputation: 383

Like
Likes
Like

Posted 01 September 2001 - 05:33 AM

oh god, something else ive just seen.

  
unsigned int width, height;
GLfloat ** verts;
GLfloat ** texs;

verts = new GLfloat * [width * 2];

for(unsigned int i = 0; i < width * 2; i++)
{
verts[i] = new GLfloat[3];
}

texs = new GLfloat * [width * 2];

for(i = 0; i < width * 2; i++)
{
texs[i] = new GLfloat[2];
}



someone needs to be slapped stupid with a very large trout. This is how the verts are gonna end up looking like:

"verts" a pointer to a pointer of floats.

"verts[0]" a pointer to 3 floats, located anywhere in mem
"verts[1]" a pointer to 3 floats, located anywhere in mem

etc etc

OpenGL just takes the pointer you pass to it ("verts") and assume that all data is stored at that location, where as infact all that''s there is pointers to more information. you need to be doing this instead:

  
unsigned int width, height;
GLfloat * verts;
GLfloat * texs;

verts = new GLfloat [width * height * 3];

texs = new GLfloat [width * height * 2];


i think that''s right.


blah, i''m in an error-finding mood. must... close.... thread... now....ARGH!!!

MENTAL

#15 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 01 September 2001 - 05:49 AM

The protected member is the pointer. The actual data is allocated on the heap, though, so I doubt that''s the problem.

#16 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 01 September 2001 - 06:06 AM

I was under the (mistaken) impression that OpenGL took an array of pointers to verteces, so what I was doing was actually what I meant to do and what I thought I had to do.

It just turns out I was very, very wrong!

#17 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 01 September 2001 - 07:10 AM

Everythings working nicely now. I''m not using glDrawElements, as that doesn''t seem suited for drawing triangle strips the way I am, but I am using interleaved arrays, which helps to make things simpler, and, because all the information for a single vertex is in adjacent memory, hopefully faster.

#18 MENTAL   Members   -  Reputation: 383

Like
Likes
Like

Posted 01 September 2001 - 02:11 PM

struct VERTEX
{
float Tex[2]; // 8 bytes
float Nor[3]; // 12 bytes
float Pos[3]; // 12 bytes
};

oh look at that, 32byte alignment. happy processor

#19 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 01 September 2001 - 03:17 PM

Nah, I''m not using that struct; mine is only 24 bytes. No alignment. Oh well!

#20 TerranFury   Members   -  Reputation: 142

Like
Likes
Like

Posted 02 September 2001 - 09:33 AM

I thought I had my problem solved. I did. But I'm moving on to improve my code, and I've realized a few things. The first is that glDrawElements is the fastest way to do what I want to (contrary to what I had mistakenly said before), and the second is that interleaved arrays won't work for what I'm tying to do now.

So I tried switching back to seperate vertex, color, and texture coordinate arrays, and creating an array of triangle strips.

First, let me explain what my understanding of what I have to do is, so that you can correct me up-front if I'm wrong anywhere.


A struct's size is equal to the sum of the sizes of it's components. That includes arrays. Therefore, an array of structs containing arrays (as different from an array of structs containing pointers to data allocated on the heap) is contiguous in memory. OpenGL's batch processing (list and array) functions require that all data is contiguous in memory.

If it's being used to draw triangle strips, glDrawElements will take the number of triangle strips to draw and an array of triangle strips. Each triangle strip is a struct containing a static array of Gluints. Each number in that struct is an array index for the arrays of verteces, colors, etc, specified using gl******Pointer commands.

In order to do this, I took the following approach. A linear array of verteces, colors, and texture coordinates is created from a heightmap, in "reading order." With verteces in this configuration, given an x, y coordinate, it is easy to determine the corresponding linear coordinate in the array. Then, each triangle strip is created from these using a pretty straightforward grid triangulation technique:


Triangle strip order: Order of verteces in array:

1____3____5 1____2____3
| /| /| | /| /|
| / | / | | / | / |
| / | / | | / | / |
2/___4/___6 4/___5/___6


Triangle strip indeces: 1, 4, 2, 5, 3, 6


As you can see, each pair of numbers in my triangle strip can be classified as {n, n + width}.


Now that you understand what I think I should be doing and what my code hopefully does, assuming no logic errors or typos or anything of that nature, you should be able to either stop me and tell me I've got everything wrong or at least better understand the following code:

The class exists in its own file. This is immediately before it, so as to avoid too many "magic numbers":
        
static const unsigned int view_x = 75 * 2;
static const unsigned int view_y = 125;
static const unsigned int half_view_x = view_x / 2;


The following structs are public members:
              
class terrain
{

public:
struct vertex
{
GLfloat dat[3];
};

struct texcoord
{
GLfloat dat[2];
};

struct color
{
GLfloat dat[4];
};

struct tristrip
{
GLuint indices[view_x * 2];
};
//...



The following protected members...
              
vertex * verts;
texcoord * texs;
color * cols0;
color * cols1;
tristrip * strips;


...are initialized in the constructor like so:
              
verts = new vertex[view_x * view_y];
texs = new texcoord[view_x * view_y];
cols0 = new color[view_x * view_y];
cols1 = new color[view_x * view_y];
strips = new tristrip[view_y - 1];


And finally, my draw function fills them out and passes them to OpenGL:
        
public:

bool draw(camera_struct& camera)
{
unsigned int top, bottom, left, right;
top = camera.y - view_y;
bottom = camera.y;
left = camera.x - half_view_x;
right = camera.x + half_view_x;



unsigned int n = 0;
for(unsigned int y = top; y < bottom && y < height; y++)
{
for(unsigned int x = left; x < right && x < width; x++)
{
putvertex2(x, y, n);
n++;
}
}


unsigned int stripnum = 0;
n = 0;
for( y = top; y < bottom - 1 && y < height - 1; y++)
{
unsigned int indexnum = 0;
for(unsigned int x = left; x < right && x < width; x++)
{
strips[stripnum].indices[indexnum] = n;
indexnum++;
strips[stripnum].indices[indexnum] = n + view_x; //one vertex south

indexnum++;
n++;
}

stripnum++;
}

glVertexPointer (3, GL_FLOAT, 0, verts);
glTexCoordPointer(2, GL_FLOAT, 0, texs);
//glColorPointer(4, GL_FLOAT, 0, cols0);


glBindTexture(GL_TEXTURE_2D, texture[0]);
glDrawElements (GL_TRIANGLE_STRIP, view_y - 1, GL_UNSIGNED_INT, strips);

return true;
}


This, I hope, will be my last "'vertex array' question." If anyone can solve it, I would be very appreciative.

[Edited for clarity and to fix some code]

Edited by - TerranFury on September 2, 2001 5:38:17 PM




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS