[Bf-committers] 'Why armatures are so slow' Report

Laurence Bourn bf-committers@blender.org
Mon, 7 Jul 2003 10:41:50 +0200


Hello,
I thought about a similar idea when implementing the IK solver. There is a
little bit of code (in the ik module) that tests to see if the end effector
is beyond the reach of the bones and terminates early if the bones are lined
up with the end effector. Although this is dangerous as you may get discrete
jumps in orientation of the bones as you cross the reachable/non-reachable
boundary. It is also not particularly flexible as it becomes much more
difficult if you implement angular constraints or different joint types in
the future(which is well within the possibilities of the ik solver module).
The reason for the slowness is also inherent in the ik solving algorithm. 

Technical bit ...

The current implementation uses an inverse Jacobian solver. By definition
when the end effector is unreachable and as the bones begin to line up the
jacobian starts to lose rank (becomes singular). All of the partial
derivatives making up the jacobian end up in the same plane perpendicular to
the actual direction you want to go :-( You have to be very careful when
computing the inverse that your solution is not a long way from the current
bone configuration. There is a little piece of math that works out the
unstable directions and chooses a time step that guarentees a bound on the
movement in those directions. 

So not a very useful post on my part. I don't know how to solve the speed
problem when the end - effector is not reachable, within the current ik
algorithm. I do not believe it's an implementation problem (;-) but
something fundamental in the solving algorithm. Which may of course mean
it's inappropriate for our use... But there really is a lot of potenial to
expand the current implementation.

Cheers,
Laurence.



> -----Original Message-----
> From: Nathan Vegdahl [mailto:nathan_vegdahl@yahoo.com]
> Sent: 05 July 2003 23:45
> To: bf-committers@blender.org
> Subject: Re: [Bf-committers] 'Why armatures are so slow' Report
> 
> 
> Yay!  I got a chance to get online again!
> 
>    Anyway, one problem that I noticed is that if the target 
> for an IKA chain is
> beyond the range of that chain (i.e. further away from the 
> chain's origin than
> the sum of the lengths of the bones) it still calculates all 
> the itterations
> even though it's impossible for it to get within the 
> thresh-hold distance. 
> Calculating all of the itterations obviously results in a 
> severe slow-down.
>    This could be solved by making sure that the target is 
> within the range of
> the chain (internally while solving, at least; it could be 
> invisible to the
> user).
> 
> --Nathan "Cessen" Vegdahl
> 
> --- Chris Want <cwant@ualberta.ca> wrote:
> > 
> > This is a just a little bit of a brain dump(tm) to share my findings
> > on the causes for slowness in the armature system.
> > 
> > The main finding is that there is too much recalculation of poses
> > and deformation/displist's at unnecessary times. It appears that
> > the NaN programmers started working on a pose/constraint caching
> > feature to alleiviate this, but it was not finished. Finishing this
> > work and expanding on it will lead to a vast increase in 
> the response
> > time while animating characters.
> > 
> > Anyways, here are some important parts of the code that 
> influence the
> > interactive speed:
> > 
> > *** source/blender/blenkernel/intern/armature.c ********************
> > 
> > - void where_is_bone1_time (Object *ob, Bone *bone, float ctime)
> > 
> >    This function figures out where a bone is based on a pose
> >    and constraints. The important speed up to note is that it
> >    does very little work if (chan->flag & PCHAN_DONE) in which
> >    case it just uses a cached matrix, which generally would be
> >    the way to go if the armature isn't being modified (either
> >    explicitely or implicitely via a constraint).
> > 
> > *** source/blender/src/drawview.c **********************************
> > 
> > - void drawview3d(void)
> > 
> >    This function draws the scene you see in the 3D window
> >    during every redraw. The big bottle neck here is this
> >    little gem:
> > 
> > 	/* Clear the constraint "done" flags */
> > 	for (base = G.scene->base.first; base; base=base->next){
> > 		clear_object_constraint_status(base->object);
> > 	}
> > 
> >    Remember the pose caching I talked about earlier? This function
> >    makes it recalculate the matrix in the cache. Since this is
> >    done every redraw things get sloooooooowhoa!
> > 
> > *** source/blender/src/editarmature.c *****************************
> > 
> > - void draw_armature(Object *ob)
> > 
> >    This function draws the armature. The source of slowness
> >    here is this stuff:
> > 
> > #if 1   /* Activate if there are problems with action lag */
> >                  apply_pose_armature(arm, ob->pose, 0);
> >                  where_is_armature (ob);
> > #endif
> > 
> >    Remember where_is_bone1_time, which would recalculate poses if
> >    they weren't cached? Well, that gets called for each bone through
> >    the where_is_armature function.
> > 
> > *** source/blender/src/drawobject.c ********************************
> > 
> > - void draw_object(Base *base)
> > 
> >    OK enough about armatures ... what about those objects that are
> >    deformed by armatures? Well, they get recalculated every redraw
> >    too!
> > 
> > #if 1
> > #ifdef __NLA
> >                          /* Force a refresh of the display 
> list if the 
> > parent is an armature */
> >                          if (ob->parent && 
> ob->parent->type==OB_ARMATURE 
> > && ob->partype==PARSKEL){
> > #if 0                   /* Turn this on if there are problems with 
> > deformation lag */
> >                                  where_is_armature (ob->parent);
> > #endif
> >                                  if (ob != G.obedit)
> >                                          makeDispList (ob);
> >                          }
> > #endif
> > #endif
> > 
> >    (man I hate comments/indenting that spans beyond 80 
> characters ... but
> >    that's another story).
> > 
> > 
> **************************************************************
> **********
> > 
> > So what to do?
> > 
> > Unfortunately, it turns out that the naive disabling of any 
> of the bits
> > of code above leads to a character that does not 
> update/pose correctly.
> > 
> > The 2 most important things to do to improve the system to prevent
> > armature slowness are thus:
> > 
> > 1) figure out when is the best time to recalculate a pose. 
> This would
> > include:
> > 
> > - Frame changed
> > - Enter pose mode
> > - Exit pose mode
> > - In the while loop in transform, i.e., 'g', 's', 'r' in 
> pose mode... 
> > and also
> >    after you press esc in there.
> > - The target of a constraint on the armature has changed
> > - any others? (I noticed intrr added some code to clear 
> constraints on
> >    'set scenes' so some care will be needed).
> > 
> > 2) figure out when the best time to recalculate the deformation of a
> > child mesh of an armature. This would basically include all of the
> > events listed above in 1), but with the added consideration that it
> > must be in very good sync with the pose calculation to avoid lags.
> > 
> > Anyways, through experimentation I have on my local source 
> tree a system
> > which has most of this stuff sorted out, with excellent interaction
> > times, but occasionally gets a little out of sync between pose
> > calculation, deformation calculation, and redraws. The 
> interaction time
> > while transform()-ing in posemode isn't great because I have it
> > recalculating the whole armature as it goes through each 
> cycle of the
> > event loop, but that can be improved by making it only 
> recalculate the
> > bones that need it, and also by only recalculating when the mouse
> > position changes.
> > 
> > I will continue to experiment ...
> > 
> > Chris
> > 
> > P.S. On an only partially related note, it might be good to replace
> > some code in drawview3d that is flagged as /* SILLY CODE!!!! */
> > with a non-silly alternative... if the code is silly it means it's
> > broken or poorly understood and it should be re-evaluated.
> > 
> > _______________________________________________
> > Bf-committers mailing list
> > Bf-committers@blender.org
> > http://www.blender.org/mailman/listinfo/bf-committers
> 
> 
> __________________________________
> Do you Yahoo!?
> SBC Yahoo! DSL - Now only $29.95 per month!
> http://sbc.yahoo.com
> _______________________________________________
> Bf-committers mailing list
> Bf-committers@blender.org
> http://www.blender.org/mailman/listinfo/bf-committers
>