Display Lists, other ways to speed up code

Started by
53 comments, last by medevilenemy 16 years, 3 months ago
noted, small_duck, I'll look into that. In the meantime my focus is still on the terrible slowness of my modelling routines [cool].
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Advertisement
In your draw function...

void DrawObj(ObjModel dat, int img, float x, float y, float z);


...Assuming that this is a fairly complex class with all of the model data in it. It should most definitely be passed by reference. The way you currently have it it is copying all of the data to another location every time you call the function. Try something like this:

void DrawObj(const ObjModel &dat, int img, float x, float y, float z);


The "const" is just to promise that you won't change the data.

Depending on the size of your model... this will speed it up.
change made, no appreciable change in speed (still sitting around 68fps on my dev machine)
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Interesting, I thought it would make at least a noticeable change. Either way, it is normally a better idea to pass large objects by reference.
A little more research has turned up basically nothing. There seem to be plenty of people who have asked about doing just what I'm looking to do, but no real examples of implementation. Sorry for being a pain.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
When you say you render the stars way out in the distance, what sort of distance are you talking about? If you mean so far away that the stars appear to stay in one place while you move around, then there is definitely no need to render each one individually. You can just draw a textured box around the world. The box doesn't even need to be big; you can draw it before anything else and disable z-buffering, like how a skybox works.

Games that take place at much smaller scales sometimes use textures to draw far more detailed 3d objects when the distance is great enough that the difference between the 2d imposter and the real 3d model is not too noticable. With stars, the distance is so great and the detail is so small that there is no way to tell the difference.
That is a good idea, however I don't think the speed increase would justify the change (the starfield is already very very fast with the new display-listed method). I may revisit this in the future, but for now I'm really more concerned with speeding up my currently abysmal model loading and drawing routines. Thanks for the suggestion, though, I'll note it for future reference.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Drawing a 12-triangle box instead of 20.000 triangles is definitely going to be faster, and with a decent texture resolution no one will notice the difference. Another thing to consider is, that with textures you can also include high-detail nebulas and planets rendered along with the stars, and it will not cost you anything speed-wise.

For your model-rendering code, you have to create a new vertex index buffer. The one you are using now, dat.TriangleArray, has indices for each of the seperate elements of your model (vertices, normals, texcoords, etc.), and OpenGL vertex arrays cannot handle this kind of interleaved indices. The number of vertices is also not likely to match the number of normals or texture coordiantes. Depending on how the data of the model is structured, you may also need to unpack the normal- and texture coordinate buffers, so they match up with the vertices of the model. Some pseudo code to do this would be:

void PreprocessObj(ObjModel &dat){	int* new_indices = new int[dat.NumVertices];	Vector3* new_normals = new Vector3[dat.NumVertices];	Vector2* new_texcoords = new Vector2[dat.NumVertices];	for(int i=0; i<dat.NumTriangles; i++)	{		for(int j=0; j<3; j++)		{			new_indices = dat.TriangleArray.Vertex[j];			new_normals = dat.NormalArray[dat.TriangleArray.Normal[j]];			new_texcoords = dat.TexCoordArray[dat.TriangleArray.TexCoord[j]];		}	}	// Free the old data	delete [] dat.TriangleArray;	delete [] dat.NormalArray;	delete [] dat.TexCoordArray;	// Replace with new and unpacked data	dat.IndicesArray = new_indices;	dat.NormalArray = new_normals;	dat.TexCoordArray = new_texcoords;}


You can do this simple preprocessing step when you load the model. You can now draw the model like this:

void DrawObj(const ObjModel &dat, int img, float x, float y, float z)  // Draw the actual object{	glColor4d(0.0, 0.0, 0.0, 1.0);	glBindTexture(GL_TEXTURE_2D, img);	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	glEnable(GL_TEXTURE_2D);	glEnableClientState(GL_VERTEX_ARRAY);	glEnableClientState(GL_NORMAL_ARRAY);	if(dat.NumTexCoord > 0)	{		glEnableClientState(GL_TEXCOORD_ARRAY);		glTexCoordPointer(2, GL_FLOAT, 0, dat.TexCoordArray);	}	glVertexPointer(3, GL_FLOAT, 0, dat.VertexArray);	glNormalPointer(3, GL_FLOAT, 0, dat.NormalArray);	glDrawElements(GL_TRIANGLES, dat.NumTriangle*3, GL_UNSIGNED_INT, dat.IndicesArray);	glDisableClientState(GL_VERTEX_ARRAY);	glDisableClientState(GL_NORMAL_ARRAY);	if(dat.NumTexCoord > 0)		glDisableClientState(GL_TEXCOORD_ARRAY);	glDisable(GL_TEXTURE_2D);	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);}


I'm not guaranteeing this code is perfect, but it should guide you in the right direction. Good luck!
<bows to the amazing pseudocode helpfulness>
Thanks very much, that is exactly what i've been looking for. I'll get right to working on that, and hopefully I'll get it to work. Looks relatively simple, in any case.

As for the starfield, I guess I'm just wary of essentially painting my background in. For my last game (2D motion, 3D graphics) I used a simple textured quad and it really looked pretty bad (programmer art, I suppose). Another thing is that atm all my textures/2D art is in .bmp format which really is nowhere near practical for high resolution images. I will need a loader/renderer for a better format in order to make the thing look any good without using up an ungodly amount of RAM (not to mention disk space).

Thanks again, though.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
I'm working on implementing the vertex array stuff now, first I'm trying to get the rendering code working (partially because I just want to see what happens [grin]). One question: what is this "IndicesArray" that you use? My .obj loader has no overall list of vertices, or a count of vertices. Perhaps Its something I have to add myself (I will attempt to do so)
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

This topic is closed to new replies.

Advertisement