Skip to main content
GameDev.net gamedev.net
🔒 Locked

opengl matrix performance

Started by blubberbert Sep 13, 2010 at 8:54 AM 4 replies 1k views
Original Post
blubberbert
blubberbert
im using the following code to obtain a bones absolute matrix in a skeletal animation structure:
void Bone::getMatrix(GLfloat time, GLfloat *matrix){	list<Bone *> parents;	Bone *b = this;	while(b->getParent() != NULL)	{		parents.push_front(b->getParent());		b = b->getParent();	}	glPushMatrix();	glLoadIdentity();	KeyFrame f;	for(list<Bone *>::iterator it = parents.begin(); it != parents.end(); it++)	{		f = (*it)->getFrame(time);		glRotatef(f.angleX, 1.0f, 0.0f, 0.0f);		glRotatef(f.angleY, 0.0f, 1.0f, 0.0f);		glRotatef(f.angleZ, 0.0f, 0.0f, 1.0f);		glTranslatef(f.length, 0.0f, 0.0f);	}	f = getFrame(time);	glRotatef(f.angleX, 1.0f, 0.0f, 0.0f);	glRotatef(f.angleY, 0.0f, 1.0f, 0.0f);	glRotatef(f.angleZ, 0.0f, 0.0f, 1.0f);	glGetFloatv(GL_MODELVIEW_MATRIX, matrix);	glPopMatrix();}

however it is terribly slow :(
are there any GL-functions i should avoid or how else could i improve the performance?
btw im currently running this function 1500 times per frame (to test performance) and the bone im obtaining the matrix for has 4 parent bones...

[Edited by - blubberbert on September 13, 2010 11:08:29 AM]
------------------------------
Join the revolution and get a free donut!
21st Century Moose
21st Century Moose
I suspect that glPushMatrix and glPopMatrix are to blame here as they will cause OpenGL to update quite a bit of internal state, which you're not even using to do any drawing with. You may be better off using glLoadMatrixf with your own copy of the identity matrix instead, or else using a software matrix library to evaluate your translations and rotations.
Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls. 
Hodgman
Hodgman
	GLfloat matrix[16];	glPushMatrix();	glLoadIdentity();	glRotatef(...);	glTranslatef(...);	glGetFloatv(GL_MODELVIEW_MATRIX, matrix);	glPopMatrix();
Code like this should probably not be using OpenGL at all - you don't need to be communicating with the driver to perform those actions.
In the above code, you just need a math library for doing matrix multiplications, rotations, translations -- however, you're asking the user's graphics card driver (from ATI, nVidia, Intel, ...) to do these operations.

The only matrix functions from GL that I'd use are probably glMatrixMode, glLoadMatrix and glLoadIdentity -- translations and rotations should be done by your own math library.

Furthermore, seeing as graphics drivers are designed to send data to the GPU (and not supply much data back to the CPU), a good rule of thumb is to assume that any glGet* function is likely to be non-optimal.

[edit]
Also, CPU wise - you can optimise your function by removing the std::list.
At the moment you're iterating through all the parent pointers and pushing them into a list (which requires a lot of small heap allocations) and then iterating the list.
One way to reduce these allocations would be to push onto the back of a std::vector, and then iterate the vector in reverse.
Alternatively you can eliminate the need for heap allocations by writing it as a recursive function.

You could also have each node cache it's absolute transform, so that you don't need to iterate through the complete parent hierarchy -- you'd just concatenate onto the absolute transform of your immediate parent.
blubberbert
blubberbert
i found the problem being the glGetFloatv calls most likely, meaning i cant use opengl for those calculations
seems like i need to get my own maths lib running :(
------------------------------
Join the revolution and get a free donut!
Zakwayda
Zakwayda
Quote:
seems like i need to get my own maths lib running :(
There are plenty of free math libraries available; you can find a list here.
21st Century Moose
21st Century Moose
The one thing to beware of is mixing a matrix library with OpenGL's matrix functions - sometimes they can give results that are subtly (and sometimes not-so-subtly) different, meaning that geometry that would normally be lined up properly would no longer be (a few pixels out here, a few pixels out there). I definitely found this to be the case when mixing my own home-grown rotation/translation (copied directly from the OpenGL spec) with glRotatef/glTranslatef calls on the latest NVIDIA drivers.

It's not that big a deal to fully implement all of your transforms in a matrix library though, and you can ease the transition by writing small wrapper functions around the library that mimic the format and params of the native OpenGL calls.
Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls. 

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.