Sign in to follow this  
Bejan0303

OpenGL Skeletal Animation Issues

Recommended Posts

Hello all,

I have recently been playing with the ms3d files and implementing skeletal animation and loading it. I load the model and the skeleton seperately, so I can attach more than one model to the same skeleton. Then I create ModelInstances and SkeletonInstances, and they are where all transforms and joint evaluations happen.
My problem: my frame rate takes a huge dive with just a simple humanoid skeleton being animated. The only thing being drawn is the animated model. Its below 50. Is this normal?? I can't imagin professional games find this acceptable.

The steps I take to animate:
Evaluate the joints in skeletonInstance.
Transform each individual vertice into a temporary array.
Then I deference the model triangle list into an array with the newly transformed vertices( I figured this would draw faster than any other way).
Copy this into a buffer and dump it to the renderer.

I am using Direct3D 9, but I am pretty familiar with openGL if anyone has any examples in either API. If example code is needed I can post some. It just seemed very messy to post so if I could avoid it I would. Thanks a lot!

Also if my hardware is relevant:
2x 3.2Ghz pentium 4
256MB ATI Radeon 9800 XT

Share this post


Link to post
Share on other sites
Are you transforming every vertex on the CPU?
There are different ways to do it on the GPU instead. You could upload a matrix for every bone, and transform each vertex according to a bone-id which you previously set.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bejan0303
The steps I take to animate:
Transform each individual vertice into a temporary array.
Then I deference the model triangle list into an array with the newly transformed vertices( I figured this would draw faster than any other way).
Copy this into a buffer and dump it to the renderer.


this is not efficient. i think you should be passing these into vertex buffers like usual, and then passing your bones and such things to a vertex shader for evaluation.

"Transform each individual vertice into a temporary array." this is certainly not the way to do it.

Share this post


Link to post
Share on other sites
Wow you guy responded fast! Yes definately all on CPU. I have never used aa shader to do something like that.
Could post of psuedo code on that? Also is the full list triangle vertices not triangles with indices to vertices, so I figured a temporary array would be good to only transform each vertice. If how would you guys go about that then.

Thanks so much for the quick replies!

Share this post


Link to post
Share on other sites
for what it's worth, you can get good speeds by doing this on the CPU too (i know several retail games that do this).

Also, doing it on the GPU might be the good answer here, but if you are GPU bound, it's a better idea to do it on the CPU.

just fyi!

Share this post


Link to post
Share on other sites
well thanks I can see that it works and animted correctly but when mke two instances frame rate hits 20 or less. I think I'm just doing something in correctly do you think copying from the temporary array to the triangle list is takin all the time?

Share this post


Link to post
Share on other sites

It's tempting to go guessing at the reasons for why your code would be so slow (my bet would be the copying step into the buffer), but the best advice is probably that you should profile your code to find the bottleneck. It may be something as simple as locking with the wrong flags, but it might also be any of a number of obscure problems I can think of.

Skinning on the GPU is typically an order of magnitude faster though, because the vertex transforms take place on specialized hardware and it doesn't require any buffer locking or copying. The DirectX SDK should have some samples on skinning which may be worthwhile to look into.

Share this post


Link to post
Share on other sites
When you say temporary array, do you mean something that you allocate each frame? In that case it would probably help to keep the array around.

Share this post


Link to post
Share on other sites
Use the debug runtime, it can give you performance warnings.

Also, are your vertex buffers dynamic? If not, they should be. There's a section in the SDK documentation on how to use dynamic vertex buffers.

Share this post


Link to post
Share on other sites
Ok I looked at the msdn documents and saw some flags to fix and stuff. It did up my frame rate but only too 70 with just the skeleton. I did just realize I don't think its the copy, when I comment out the once per frame copy, it only bumps up the frame rate to about 95. On the other hand when I comment out the "EvaluateJoints" and the "TransformVertices" functions the frame rate is like 2000+ ( that sounds high, but the total triangles rendered is only 700 so I believe it). That leads me to believe my functions are sucking!

Thanks again

Share this post


Link to post
Share on other sites
When you profile, don't look at FPS, look at how long each frame took (in milliseconds most commonly)

Check this out...

let's say one frame took 5 milliseconds to calculate/render. That would be 200 frames per second.

If that frame took 10 milliseconds, it would be 100 frames per second.

If it took 15 milliseconds, that is about 66FPS.

To see it more plainly look at this:
5ms = 200fps
10ms = 100fps
15ms = 66fps
20ms = 50fps
25ms = 40fps
30ms = 33fps
35ms = 28fps
40ms = 25fps

as you can see, the difference between 25fps and 28fps is the same as the difference between 100fps and 200fps!

So basically, looking at fps can be really misleading. Instead look at how many milliseconds each frame took when profiling to get a real sense of performance changes (:

Share this post


Link to post
Share on other sites
Fair enough,
I tried it your way and:
With evaluate and transforming and copy verts = 8.814 ms = 113 fps
without copy = 8.8 = 113 fps
no transform = 2.0 = 500 fps
no evaluate = 8.8 = 113fps
no transform and no evaluate with copy alone = 1.31

so they are all at least 100 fps.... I check multple times. Why would the fps counter make a different result. I just count each frame and when i hit one second checked the value.

So I probably need to optimize my tranform code thanks!

Share this post


Link to post
Share on other sites

Quote:
Why would the fps counter make a different result. I just count each frame and when i hit one second checked the value


Because as Atrix showed the distribution of the framerate is different and less useful than the distribution of elapsed time. The elapsed time is a linear function x, while the framerate is a hyperbola following 1/x where x is the elapsed time. The framerate may be more intuitive and work reasonable around a target framerate of 60, but because of the shape of the hyperbola the FPS figure becomes less meaningful as the elapsed time gets smaller (or larger, to a lesser extent).

Quote:
So I probably need to optimize my tranform code thanks!


Bear in mind that straightforward optimization of your own code may not cut it. Transforming vertices already is a quite intense floating point operation and with skinning and multiple bone weights, you'll probably be doing up to 4 times as many transforms as with normal matrix transforms. These floating point operations can be rather hard on your processor, so it might be a good idea to look for a specialized vector/matrix math library that makes use of the floating point and SIMD capabilities of your processor. I'm not sure, but I seem to recall that the XNAMath library from MS (despite its name it's meant for C++ / DirectX) uses these processor features.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this