Bendy bones and shape keys cause vertices to pop
Open, NormalPublic

Description

Hi. I'm posting this to know if this is a known limitation.

Blender Version
2.79

Short description of error
When you change the value of a shape key for a mesh that is deformed by an armature that has normal bones as well as bendy-bones, the mesh vertices will pop.

Exact steps for others to reproduce the error
Create a mesh and add an Armature modifier to it, with an armature object that has some normal bones as well as one or more bendy-bones (more than 1 subdivision). Use auto-weights or manual weight painting. Add and use a shape key on this mesh to see this behaviour.
This happens whether you're in animation playback mode or not.

I originally posted this as a Right-Click Select entry:
https://blender.community/c/rightclickselect/t0bbbc/b-bones-don-t-work-with-shape-keys

Details

Type
Bug

Currently, Bendy Bones are not replacing bones chains. Unless you have several subdivisions, you have one weight group or one enveloppe with one head and one tail per bone.
So, closed vertices may be influenced by following segments pointing to different angles at maximum intensity.
Distortion is obvious without the shapekey. The shapekey is just emphasizing gap made by skinning.

B-bones are useful to twist a part of initial mesh or to rig a curved part of the mesh . Their use for center of a sphere is irrelevant.
The shapekey was created before the skinning for a basis with closed vertices.
After that skinning creates the gap ; the shapekey becames irrelevant, too.
But there is no reason to observe a problem for a corrective shapekey made in sculpt mode.

If you use less B-bone segments than pairs of edge loops ; you will still have a noticeable problem because curvature of bone will only correspond to curvature of mesh at rest pose.
Unless you are only doing a twisting, segments cuts will still be obvious and emphasized by a pose that is creating bigger gaps between segments.
So, you have to use B-bones with a mesh part that is not dense and a subdivision surface modifier after the armature.
Or if the mesh part is detailed, you have to compensate the problem with a corrective smooth modifier.

But an automatic smoothing of weight between segments is rather a feature request or a todo than a bug.
At least, it is an already known issue.
https://youtu.be/-R1VQ1M8dM0?t=19m52s

@ronan ducluzeau (zeauro) Thank you for your observations. You're right, a sphere is not the best kind of mesh to show what I mean.
I'll try with a cylinder. So the same context as in those steps to reproduce the event from the report, but with a cylinder and some keyframes.

Shown only the armature modifier:

Shown only the shapekey animation:

And finally with both combined (armature modifier and shapekey animation):

The problem is how the swelling part of the mesh pops in place.
So this would appear in a render, for example, if you were using shape keys for correction or just for morphing (like a skinny character that becomes big and muscular).
Increasing the b-bone subdivisions and using a Corrective Smooth modifier seems to make this behaviour less noticeable (the pops get more subtle).

It indeed seems like a known limitation, but maybe @Joshua Leung (aligorith) can share his wisdom? move to TODO?

I think it has to do with this logic here:
https://github.com/dfelinto/blender/blob/master/source/blender/blenkernel/intern/armature.c#L778-L783

Deformed (shape-keyed) vertices are assigned to b-bone segments based on their position relative to the rest-pose b-bone, so if the deformed vertices change position (like when you change a shape key strength), they become assigned to different segments (which may have a very different transform, causing the popping effect).
That's what i take from it, but I can't look into it further.

Hi. After researching some more.

This is a problem of interpolation (or lack of it).

The code is correct in taking the vertices after they are deformed (from shape keys or from modifiers earlier in the stack) and mapping them to b-bone segments.
But this code here considers a vertex as being deformed by a single b-bone segment at a time:

/* now calculate which of the b_bones are deforming this */
segment = bone->length / ((float)bone->segments);
a = (int)(y / segment);

Knowing this, we can make a scene with the worst case scenario, a two-segment b-bone with a sharp curve:


(The stuff on the right side is just a duplicate, where the b-bone segments are scaled so you can tell them apart. This scene can be used as a template for testing solutions to this.)

@Joshua Leung (aligorith) had mentioned this in an article in the past:

(...) any questions regarding the quality of B-Bone deforms, or how those work are not covered here.

For details about those, go consult the armature modifier for further details about how it uses the B-Bone info gained from b_bone_spline_setup(). My guess is that it calculates delta matrices for each segment, and then interpolates between these to deform points that are affected by such bones. Smoother deforms may be possible if we added an extra smoothing step in there somewhere, instead of just using the result.

I think the solution is localised to the b_bone_deform function in armature.c.
Like, the fractional part...

(y/segment) - (int)(y/segment)

...could be used to interpolate the deformation being done on the vertex, such as SLERPing the rotations of the segments that the vertex is closest to along the Y-axis of the b-bone local space, like it's being done now to map it.
Since a b-bone tries to fit a bezier curve, the ideal deformation that this interpolation should cause on a mesh with shape keys \ deform modifiers earlier in the stack would probably be like the Curve modifier, which does something similar.
Anyway, I think it's a to-do. Good luck!