Onkba’s animations fall back on the CPU. How can I ensure my models won’t ?

Software: Away3D 4.x

SuperSam, Sr. Member
Posted: 21 April 2013 10:44 PM   Total Posts: 102

Hi,

I would like to know how to make sure that a 3DS Max 2014 model has its animation performed on the GPU and not the CPU.


That’s about it. If you need more details to get what I mean, read on. smile

The model Onkba from Away3D dev branch examples has its animation ran on the CPU. I profiled it and basically 92% of the code execution time was spent in skeletonAnimator.morphGeometry. D’oh !


This is probably because this SkeletonAnimator method:

public function testGPUCompatibility(pass MaterialPassBase) : void
{
    
// NOTE: I made sure _forceCPU was false and _jointsPerVertex equals 3
    
if (!_useCondensedIndices && (_forceCPU || _jointsPerVertex || pass.numUsedVertexConstants _numJoints 128)) {
        _animationSet
.cancelGPUCompatibility();
    
}

So I suppose the real culprit is Onkba, the model is not done “properly”.

Which led me to the question:

What do I need to pay attention to if I want animations of a 3DS Max 2014 model to run on the GPU ? Failing that, how can I make a model with an animation that is light on the CPU ?


Thanks for your help!

   

SuperSam, Sr. Member
Posted: 21 April 2013 11:41 PM   Total Posts: 102   [ # 1 ]

I’ll try to answer myself but it would be good if I had someone correcting me. I’ll color in red the 3 questions that rose from my digging of the code.

*  One vertex may not have more than 4 bones attached to it, otherwise animations will fallback on the CPU.


* Apparently, it’s best when a model has at most 32 bones. It can have more, but then animation may occur on CPU. But not necessarily.
Why is it 32 ? According to _numJoints it’s not a hard limit, it can be anything as long as pass.numUsedVertexConstants + _numJoints * 3 <= 128
I have seen numUsedVertexConstants take values from 5 to 9. Onkba has 40 bones, so the DistanceMapPass (9 constants used) must be the one that kicks it back to the CPU… (9 + 40 * 3 = 129)


* When there are too many bones, it seems to be good that our animations have at least 2 meshes, so that Away3D can use _useCondensedIndices which will keep animations on the GPU.
- Why is it so ? What makes this case less complicated than the previous 40 bones, single mesh situation ?

I could have left a bunch of other fallbacks for all I know, so:
- Are there other guidelines to avoid CPU fallbacks when making 3D models ?

   

CyrilM, Newbie
Posted: 22 April 2013 02:24 PM   Total Posts: 15   [ # 2 ]

I’ve beeen running across the same stuff you have with the animation system. What I figured out is that when the bone information is transferred to the gpu it needs space in the vertex constant registers to do it. There are only 128 in AGAL. This means that the first 5 (used by the transform matrix of every model) are taken and any others used by any other shaders. Each bone, it seems, needs three vertex constants to work. Likely position, scale and rotation. This means that you have 128 - 5 / 3 = 41. So in the best case scenario you have at most 41 bones.

im not sure how __usecondensedindicies works. I’ve tried it once with very limited success. It still rendered but the mesh was all over the place while it was animating.

The best bet, for now, is to try to keep the bone limit as low as possible, or cut up your animation into two meshes and try to animate them at the same time. I manually call the update function to make sure that my animations are synced together.

Until Away3D supports more bones, or Flash increases their resources limits for stage3D we are pretty much stuck with that.

   

SuperSam, Sr. Member
Posted: 22 April 2013 03:38 PM   Total Posts: 102   [ # 3 ]

Awesome ! 41 bones at most. Now if we factor in the children of MaterialPassBase such as DistanceMapPass, which takes 9 vertex constants and is the most demanding of all we get a maximum of…(128 - 5 - 9) / 3 = 38 bones! Dang, still not 32 :p


Now about your tricks for using higher number of bones… By cutting animation into two meshes, you probably mean inside the same model file, i.e. the appropriate case scenario for _useCondensedIndices. So if I get you correctly, without condensing indices you can still get animations on the GPU by instantiating two different meshes out of that file, and for both do

var activeAnimation:AnimationNodeBase mesh.animator.activeAnimation;
var 
msTime:int int(mesh.animator.absoluteTime);    // Casting because absolute time is a Number for some reason
mesh.animator.getAnimationState(activeAnimation).update(msTime); 


Is that correct and is that all ?

Also how do you make sure update isn’t called a second time by Away3D inner classes ? Do you do something special to disable updating for these 2 mesh animations ? Not disabling won’t cause problem because update takes an absolute time so it does not matter how many times it is called, but it might affect performance when you update all your meshes manually.


Edit: It would be nice if Away3D took advantage of ASC 2.0 inlining.
As for Stage3D getting more vertex constants…perhaps it will in the extended profile. I hope Adobe didn’t drop development of that profile though.

   

CyrilM, Newbie
Posted: 22 April 2013 04:58 PM   Total Posts: 15   [ # 4 ]

In my code I use AnimatorBase.autoUpdate = false; to stop the animations from playing automatically. Then I can ensure that they all play at the correct time.

To actually update the animation I keep a list of the .animation objects and call each like so

var _time int getTime();
for ( var 
int 0_animatorList.lengthi++)
{
    
if ( _animatorList[i].isPlaying )
        
_animatorList[i].update(_time);

There is more code to it than that, but that is the gist of what i’m doing.

Seems to work perfectly in our code. I haven’t tried it your way, but that might work as well.

   

SuperSam, Sr. Member
Posted: 22 April 2013 08:33 PM   Total Posts: 102   [ # 5 ]

Oh I see ! My bad. You’re using AnimatorBase.update function when I was looking into AnimatorStateBase.update. That sounded strange.

Calling AnimatorBase.update manually seems to be fully supported by Away3D. Thanks for pointing me to it. I’ll probably be using it from now on as it’s IMO preferable to control updates from the main loop.

Now I just need to find how to make 32 bones skeletons and decent models that look like they have been made by at least a 10 years old. smile

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X