Vertex array question

Started by
9 comments, last by adam17 16 years, 11 months ago
right now im trying to build a terrain renderer. at the moment im trying to add in normals into the pipeline. i have the code for building the normals, thats not the problem. ive noticed that everytime i draw the arrays using glNormalPointer and glDrawArrays, i get an access violation (im accessing outside the array of normals). i have all of the normals packed into the array as just vertex normals. im drawing the triangles as a triangle strip. as the card is drawing the mesh, is it using the array i put into glNormalPointer as a index and reference system or is it 1:1 as its drawing the triangles? hopefully im making sense
Advertisement
Can you post the relevant code, it would be easier to help you.

Moved to the OpenGL forum - you'll probably get more help there.
ok my code is a little messy, but hopefully it will make sense. ill try to comment each section.

int width_vert;int length_vert;const GLfloat terrain_width = 100;const GLfloat terrain_length= 100;const GLfloat terrain_height= 50;int size;GLfloat*				tri_arr=NULL;GLfloat*				norm_arr=NULL;GLfloat*				vert_arr=NULL;void LoadTerrain(Texture_data dat){	std::vector<Vector3>	arr;	std::vector<Vector3>	tristrip;	std::vector<Vector3>	norm;	std::vector<Vector3>	inter;	int q=0;	width_vert = dat.width;	length_vert= dat.height;	size = (width_vert*2)*(length_vert-1);    //load terrain vertices from image data    arr.resize(width_vert*length_vert);	int zoffset=-1;	for(int i=0; i<(width_vert*length_vert); i++)	{		if((i%length_vert)== 0)			zoffset++;		arr.x = ((float)(i%width_vert)/width_vert)*terrain_width;		arr.y = dat.image_data[i*3]*(terrain_height/255);		arr.z = ((float)zoffset/length_vert)*terrain_length;	}		//construct triangle strip data from vertices	for(size_t i=0; i<arr.size()-width_vert; i++)	{        if((i%width_vert) == 0)             tristrip.push_back(arr[i+width_vert]);                tristrip.push_back(arr[i+width_vert]);        tristrip.push_back(arr);                     if(((i+1)%width_vert) == 0)             tristrip.push_back(arr);		q++;    }	Log<<"tristrip array contains degenerate triangles. 2 degenerate triangles per row"<<std::endl;	Log<<"q           ="<<q<<std::endl;	Log<<"tristrip    ="<<tristrip.size()<<std::endl<<std::endl;	//convert tristrip to GLfloat* array tri_arr	tri_arr = new GLfloat[tristrip.size()*3];	for(size_t i=0; i<tristrip.size(); i++)	{		tri_arr[i*3+0] = tristrip.x;		tri_arr[i*3+1] = tristrip.y;		tri_arr[i*3+2] = tristrip.z;	}        //convert arr to 2D array for easier normal calculation	std::vector<std::vector<Vector3>>temp_arr;	temp_arr.resize(length_vert);	for(size_t i=0; i<(size_t)length_vert; i++)		temp_arr.resize(width_vert);	zoffset = -1;	q=0;    for(int i=0; i<width_vert*length_vert; i++)    {		if((i%width_vert)==0)			zoffset++;		temp_arr[i%width_vert][zoffset].x = arr.x;		temp_arr[i%width_vert][zoffset].y = arr.y;		temp_arr[i%width_vert][zoffset].z = arr.z;		q++;    }	Log<<"size() is length of one edge"<<std::endl;	Log<<"temp_arr    ="<<q<<std::endl;	Log<<"size()      ="<<temp_arr.size()<<std::endl<<std::endl;	//construct normals from triangle strip data	//norm.resize(width_vert*length_vert);	Vector3 v0, v1, p, n, t;	q=0;	for(int i=0; i<length_vert; i++)	{		norm.push_back(Vector3(0,1,0));		for(int j=0; j<width_vert; j++)		{			//temp_arr[j]			/*n = Vector3(0,0,0);			p = temp_arr[j];			if((j>0)&&(i>0))			{				v0 = p - temp_arr[j-1];				v1 = p - temp_arr[j-1][i-1];				n = n + Cross(v1,v0);			}			if((j>0)&&(i>0))			{				v0 = p - temp_arr[j-1][i-1];				v1 = p - temp_arr[j][i-1];				n = n + Cross(v1,v0);			}			if((j<length_vert-2)&&(i>0))			{				v0 = p - temp_arr[j][i-1];				v1 = p - temp_arr[j+1];				n = n + Cross(v1,v0);			}			if((j<length_vert-2)&&(i<width_vert-2))			{				v0 = p - temp_arr[j+1];				v1 = p - temp_arr[j+1][i+1];				n = n + Cross(v1,v0);			}			if((j<length_vert-2)&&(i<width_vert-2))			{				v0 = p - temp_arr[j+1][i+1];				v1 = p - temp_arr[j][i+1];				n = n + Cross(v1,v0);			}			if((j>0)&&(i<length_vert-2))			{				v0 = p - temp_arr[j][i+1];				v1 = p - temp_arr[j-1];				n = n + Cross(v1,v0);			}			if((n.x == 0)&&(n.y == 0)&&(n.z == 0))*/				n = Vector3(0,1,0);						n = Normalize(n);			norm.push_back(n);			q++;		}		norm.push_back(Vector3(0,1,0));	}	Log<<"norm array contains degenerate triangles. 2 degenerate triangles per row"<<std::endl;	Log<<"q           ="<<q<<std::endl;	Log<<"l*w         ="<<length_vert*width_vert<<std::endl;	Log<<"norm.size() ="<<norm.size()<<std::endl;	q=0;	norm_arr = new GLfloat[(norm.size()*3)];	for(size_t i=0; i<norm.size(); i++)	{		norm_arr[i*3+0] = norm.x;		norm_arr[i*3+1] = norm.y;		norm_arr[i*3+2] = norm.z;		q++;	}	Log<<"q = norm_arr="<<q<<std::endl;	//clear arrays	for(size_t i=0; i<temp_arr.size(); i++)		temp_arr.clear();	temp_arr.clear();	arr.clear();	tristrip.clear();	norm.clear();}void DrawTerrain(){		glEnableClientState(GL_VERTEX_ARRAY);	glEnableClientState(GL_NORMAL_ARRAY);	glVertexPointer(3, GL_FLOAT, 0, tri_arr);	glNormalPointer(GL_FLOAT, 0, norm_arr);	glDrawArrays(GL_TRIANGLE_STRIP, 0, size);	glDisableClientState(GL_VERTEX_ARRAY);	glDisableClientState(GL_NORMAL_ARRAY);}


in the DrawTerrain function, if i comment out the lines glEnableClientState(GL_NORMAL_ARRAY), glNormalPointer(), and glDisableClientState(GL_NORMAL_ARRAY) the program doesnt crash, but its not rendered properly.

[Edited by - adam17 on May 16, 2007 1:16:51 AM]
sounds like you have less normals than are indexed. Are you sure you have the same number of verts and norms?
[size="1"]
well length_vert and width_vert are the height and width of the loaded image. if i load a 256x256 image then length_vert and width_vert equal 256. in the loop where i store the normals into the array, it should be 256x256, just like the number of vertices.
YOu should load images as 257x257 one more than POT sizes, so you have 256 polygons.

glDrawArrays() takes the number of vertices you have to render, so is size in machine bytes? e.g. sizeof(float) * 65536 * 3 or is it 65536
im thinking about changing the rendering from just glNormalPointer and glVertexPointer into glInterleavedArrays. i guess i can throw GL_N3F_V3F in and see how everything works.
instead of fooling around with the interleaved arrays, i decided to log different variables in the loops into a text file. i made changes to my previous post's code to include the variables and the logging. here is the output of the log file:

tristrip array contains degenerate triangles. 2 degenerate triangles per rowq           =261632tristrip    =524286size() is length of one edgetemp_arr    =262144size()      =512norm array contains degenerate triangles. 2 degenerate triangles per rowq           =262144l*w         =262144norm.size() =263168q = norm_arr=263168
ok, now i had a VERY weird discovery. i decided to draw a quad underneath my terrain to make sure i have my temporary normal pointing in the right direction at least. i also wanted to double check my light position. well, when i draw the quad using the basic following code:
glBegin(GL_QUADS);	glNormal3f(0,1,0);	glVertex3f( 0, 0,50);	glVertex3f(50, 0,50);	glVertex3f(50, 0, 0);	glVertex3f( 0, 0, 0);glEnd();

my entire terrain lights up as if it had a normal of <0,1,0> everywhere (if you look at my posted code, im storing <0,1,0> as the temporary normal in the array). now when i comment the quad's normal out, only half of the terrain lights up (i was having this problem earlier without the quad). does this just prove that my array of normals is too small? am i missing something in the rendering pipeline which could be causing this?

ill rephrase my first question: should my normal array be the same length as my triangle strip array?

here are 2 images which my provide a better visual.
no normal:

with the normal:


[Edited by - adam17 on May 16, 2007 11:12:01 PM]

This topic is closed to new replies.

Advertisement