Slow...

Hello,
I’m trying to render some sorta bycicle i’ve downloaded. But my problem is, my pc gets really slow because of it. When I render that model, my framerate is like 3 orso. I’ve counted the number of polygons, and it consists of 60552 polygons.
So my question is, why is my program so slow?
Is it because it has to render so many polygons, or is it manually because the way I render my scene?
Because I gues most video games that are currently out, use much more polygons to render there levels.
But I do use display lists and the depth buffer.
I just wanted to be certaint whether it’s my crappy code or the number of polygons.
– Begin edit –
My hardware:
GPU: Geforce FX 5600
CPU: AMD Athlon 2800
– End edit –
– Begin edit2 –
I’ve did some searching and found some info about my 3D card:
http://www.digit-life.com/articles2/gffx/nv31-nv34.html#p7
So if mpolygons are polygons * 10^6, then my card should be able to render atleast 18 million polygons per second.
Can anyone confirm that mpolygons are polygons * 10^6?
–End edit2 –
Thanx in advance,
Hylke

It looks like your code is the problem. But to help you we need more information about how you draw you model.

Did you write the code or are you running a demo someone wrote, if for example you’re running an HDR demo with a tricycle that someone wrote to show off FBOs then it could grind your card to a halt but not because of something as simple as polygon count.

If you didn’t write this code, (and your post makes my think you may not have), then you’re really posting in the wrong forum.

My source code is quite big.
The main files, where it all happens, are:
3DS.cpp
3DS.h
objects.cpp
objects.h

But what is basicly comes down to:

objects.cpp:

void Object::LoadModel()
{
[..]
		model->RenderModel(); // Make display lists and stuff

		listindex = glGenLists(1);
		glNewList(listindex, GL_COMPILE);
		glTranslatef(pos.at(0), pos.at(1), pos.at(2));
		if(! RotateDefault1)
			glRotatef(rotate.at(0), 1.0, 0.0, 0.0);
		if(! RotateDefault2)
			glRotatef(rotate.at(1), 0.0, 1.0, 0.0);
		if(! RotateDefault3)
			glRotatef(rotate.at(2), 0.0, 0.0, 1.0);
		if(! ScaleDefault)
			glScalef(scale.at(0), scale.at(1), scale.at(2));
		model->RenderModel(); //Calls the function RenderModel from the class Model, and not the class Object
		glEndList();
[..]
}

[..]

void Object::RenderModel() //This function differs from the function RenderMode in the class Object
{
	if(TypeModel == OBJECT_MODEL_TYPE_3DS)
	{
		glPushMatrix();
		glCallList(listindex);
		glPopMatrix();
	}
}

3DS.cpp:

void Model::RenderModel()
{
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	glShadeModel(GL_SMOOTH);
	
	if(file->lights) //if we have lights in the model
	{
		EnableLights(); //enable all lights
		glCallList(lightListIndex); //set lights.
	}
	
	Lib3dsNode *nodes = file->nodes;
	if(nodes != 0)
		for(nodes = file->nodes;nodes != 0;nodes = nodes->next) // Render all nodes <== gotta improve this
			RenderUsingNodes(nodes);
	else
		RenderWithoutNodes();

	
	if(file->lights)
		DisableLights(); // disable lighting, we don't want it have it enabled longer than necessary	
[..]
	glDisable(GL_CULL_FACE);
	glShadeModel(GL_FLAT);
}

[..]

void Model::RenderUsingNodes(Lib3dsNode *node)
{
	[..]
		if(! node->user.d) //Wheter we have a list or not, if not we're gonna create one
		{
	[..]
			node->user.d = glGenLists(1); //alocate memory for one list
			[..]
			glNewList(node->user.d, GL_COMPILE); //here we create our list
			{
				renderNode(mesh);
			}
			glEndList(); // end of list
		}
		if(node->user.d) // if we have created a link list(with glNewList)
		{
			Lib3dsObjectData *tmpdat;
			glPushMatrix(); //save transformation values
			tmpdat = &node->data.object; // get the position data
			glMultMatrixf(&node->matrix[0][0]); //adjust matrix according to the node
			glTranslatef(-tmpdat->pivot[0], -tmpdat->pivot[1], -tmpdat->pivot[2]); //move to the right place;
			glCallList(node->user.d); //render node
			glPopMatrix(); //return transformation original values
		}
}

void Model::RenderWithoutNodes()
{
	[..]
		if(! mesh->user.d) //Wheter we have a list or not, if not we're gonna create one
		{
	[..]
			mesh->user.d = glGenLists(1); //alocate memory for one list
[..]
			glNewList(mesh->user.d, GL_COMPILE); //here we create our list
			{
				renderNode(mesh);
			}
			glEndList(); // end of list
		}
		if(mesh->user.d) // if we have created a link list(with glNewList)
		{
			glPushMatrix(); //save transformation values
			glMultMatrixf(&mesh->matrix[0][0]); //adjust matrix according to the node
			
			glCallList(mesh->user.d); //render node
			glPopMatrix(); //return transformation original values
		}
}

[..]

void Model::renderNode(Lib3dsMesh *mesh)
{
	
[..]
					glMultMatrixf(&m[0][0]); //adjust our current matrix to the matrix of the mesh
				}
				[..]					if(mat) //if we have material
					{
						static GLfloat ambient[4] = { 0.0, 0.0, 0.0, 1.0 };
						glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); // Ambient color
						glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); //diffuse color
						glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); //specular color
						float shine;
						shine = pow(2, 10.0 * mat->shininess);
						if(shine > 128.0)
							shine = 128.0;
						glMaterialf(GL_FRONT, GL_SHININESS, shine);
					}
					else // if we do not have material properties, we have to set them manually
					{
						GLfloat diff[4] = { 0.75, 0.75, 0.75, 1.0 }; // color: white/grey
						GLfloat amb[4] = { 0.25, 0.25, 0.25, 1.0 }; //color: black/dark gray
						GLfloat spec[4] = { 0.0, 0.0, 0.0, 1.0 }; //color: completly black
						glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
						glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
						glMaterialfv(GL_FRONT, GL_AMBIENT, spec);
					}
					{
						if(mesh->texels)
						{
							glBindTexture(GL_TEXTURE_2D, textureIndices.at(j));
							j++;
						}
						glBegin(GL_TRIANGLES);
						for(int i = 0;i < 3;i++)
						{
							glNormal3fv(normals[3*p+i]); //set normal vector of that point
							if(mesh->texels)
								glTexCoord2f(mesh->texelL[f->points[i]][0], mesh->texelL[f->points[i]][1]);
							glVertex3fv(mesh->pointL[f->points[i]].pos); //Draw the damn triangle
						}
						glEnd();
					}
				}
 [..]
}

I did wrote this code myself.
If you want to check out all the source codes, check out:
http://svn.gna.org/viewcvs/combatofdeath/trunk/

OK, no problem, sorry for assuming you didn’t write this.

GLTRIANGLES is an inefficient way to draw stuff, basically you’re sending at least 3x more data than you need to and may be on an unoptimized path. In addition glDrawArrays or array range or some other variant is a much more efficient way to draw stuff, so you probably want to be drawing indexed meshed primitives for better performance and meshed with a view to cache coherency if you want to be really clever and allocated to be in the best memory i.e. card resident for static data, it can even eliminate the need for display list optimization.

In addition you have a lot of overheads in drawing this stuff, like matrix and material operations, that’s fine if you have a lot of polygons per primitive but if you don’t then those start to eat into your triangle rate very quickly.

The use of diaplay lists is good and helps some implementations optimize your drawing but it won’t mesh your triangles for example. That’s up to you, you’re still pretty inefficient, and when you optimize yor triangle throughput your other OpenGL operations will become an even greater portion of your rendering time and a greater concern.

Thank you for your reply.
But do you happen to know what is the average polygon rate per (game) map of, in example, Unreal Tournament 2004, so that I know what my card should be able to do?

If we stay with a simple Frame Per Second (fps) metric, I noticed that rendering your bicycle.3DS mesh costs about 20fps using my trusty 600MHz PIII with GeForce FX 5200.

For an untextured mesh, this seems like a lot to me, so while optimizing your code to improve from 3 to 30fps will be critical, you may still find that reducing your polygon count will also be necessary.

P.S. I’m using SpaceTime , which has a simple 3DS loader built in, to measure fps. It uses interleaved polygons (vertices, colours, normals) and display lists to boost frame rate.

Originally posted by <Goatboi>:
If we stay with a simple Frame Per Second (fps) metric, I noticed that rendering your bicycle.3DS mesh costs about 20fps using my trusty 600MHz PIII with GeForce FX 5200.

For an untextured mesh, this seems like a lot to me, so while optimizing your code to improve from 3 to 30fps will be critical, you may still find that reducing your polygon count will also be necessary.

So I could atleast get a framerete of 30.Ok, thats good to know :stuck_out_tongue: .

P.S. I’m using SpaceTime , which has a simple 3DS loader built in, to measure fps. It uses interleaved polygons (vertices, colours, normals) and display lists to boost frame rate.
Thanks, i’m pretty sure that will come in handy.

I didn’t read all the topic but what I can say is that how many triangles you could draw per second depends on many factors, mainly: fill rate, texturing, lighting, culling and drawing methods (display lists, vertex arrays…)