Bone heat weighting: failed to find solution for one or more bones

trying to create bone heat I got

bone heat weighting: failed to find solution for one or more bones

so, what does it mean?

Most likely you have X-Axis Mirror turned on, but your armature isnā€™t really symmetrical, i.e. a bone is named wrong on one side or another/and is out of symmetry .

Also make sure the central axis bones (bones without _L or _R extensions) are lined up properly along the X axis (select them all in Edit Mode and hit S -> X -> 0) . You might have to move one side of the L/R bones to get them to align afterwards (use L to select linked bones) .

Iā€™m not using X-Axis Mirror but I did manually duplicate, mirror and reconnect some of the bones, could that be the problem?

Yes, I think the bone heat skinning is based on having the X-Axis Mirror on . Just turn it on and see if you still get the error message . If you do do what I suggested above .

I still got that error but additionally I donā€™t want to use X-Axis Mirror because my modelā€™s not completely symmetrical.

Well then you will just have to skip using the bone heat skinning until/ if Brecht gets around to coding it for asymmetrical armatures/meshes . Youā€™ll just have to use the other options available like envelopes/weight painting/manually assigning vertex groups etc.

But if you really need the feature you can try a workaround if the asymmetry in your model isnā€™t complicated ā€¦ first just make your model symmetrical, then make an equally symmetrical armature with X-Axis Mirror on and parent etc, so the feature works . Now go into Pose mode and try simulate the asymmetry with a pose with the armature . Once you are happy with the results select all bones and hit I and set a keyframe (make sure you are at frame 1) ā€¦ Go into the Action Editor and rename the Action something like ā€œBasisā€ ā€¦ Now whenever you want to animate just open this ā€œactionā€ to start keying poses ā€¦

If you want an another level of ā€œpose securityā€ you could also add empties along the armature chain by 1) add empty 2) shift-select the bone you want he empty to be assigned to 3) SHIFT+CTRL+P to make parent without inverse (which will snap the empty to the head of the bone) ā€¦ 4) and once you have done that for the entire armature you can save the rotational data to the empty by hitting Alt-P -> Clear and Keep Transformation (Clear Track) ā€¦ Just in case some how you loose the action data or if you want to actually make the armatureā€™s rest position/edit pose the same as the mesh (ā€¦ remember the emptiesā€™ position in 3D represents the position of a head of a bone) so you could just Shift-S to get the actual position of the head/tail positions by tabing in and out from Object to bone Edit Mode ā€¦

Does anyone know the exact formula the bone heat code uses to work out that it is not happy with the armature?

I am trying to write a script to fix an armature (from MakeHuman).

Looking at the source codeā€¦ the message comes from ./source/blender/src/meshlaplacian.c around line 715. It tries to solve a Laplacian, and if that fails, it displays the message. Presumably, see http://en.wikipedia.org/wiki/Laplacian. I have looked at the code, but so far I can say that it has something to do with matrixes.

It would be nice if the code could tell us which bones had problems and perhaps even provide a second-best solution if the Laplacian does not work. At least it could fail a bit better by continuing with the other bones so that maybe only one bone needs manual weight painting, rather than stopping the whole exercise at the first bone with a problem. The code is looping through the bones in sequence, and for each one it sets up a Laplacian, solves it, and then uses it to define the weights for each vertex. I think the idea is that we get a nice smooth fall-off in the weights so that the mesh deforms evenly.

what martinellison said plus

1, from a algorithmic perspective why does it need to be x mirrored but doesnā€™t care about the other 2 axises

2, im pretty sure I have gotten bone heat to work without x mirroring before, is it possible when it gives this message their actually something about the mesh it doesnā€™t like?

I have written a script which fixed my mesh (as output from MakeHuman). When it runs, it will list all the armatures and meshes in the scene, and you need to select one of each.

This is not tested very much, so feedback would be good.


#!BPY

# """
# Name: 'Re-align Armature'
# Blender: 246
# Group: 'Mesh'
# Tooltip: '(Re)Attach an armature to a mesh and ensure that they have the same object centres.'
# """

import Blender 
from Blender import Window, Draw, Scene, Object, Mesh

__author__ = 'Martin Ellison'
__version__ = '1.0 2008/07/30'
__url__ = []
__email__ = ["Martin Ellison, m.e:acm*org", "scripts"]
__bpydoc__ = """\
From the popup, select one armature and one mesh.
 
 """

# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Martin Ellison
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender import Window, Scene, Geometry, Mathutils, Object, Armature, Mesh, Draw
from Blender.Mathutils import Vector

def alignArmature(armatureObject, meshObject):
        armatureLoc = Vector(armatureObject.loc)
        armature = armatureObject.getData()
        meshLoc = Vector(meshObject.loc)
        diff = armatureLoc - meshLoc
        armature.makeEditable()
        for bone in armature.bones.values():
                bone.head -= diff
                bone.tail -= diff
        armature.update()
        armatureObject.setLocation(meshObject.loc)

def main():
        print '-----'
        scn = Scene.GetCurrent()
        sel_object = scn.objects.active
        popup = []
        armatures = []
        meshes = []
        for obj in scn.getChildren():
                if obj.type == 'Armature':
                        tog = Blender.Draw.Create(0)
                        popup.append((obj.name + ' (arm)', tog))  
                        armatures.append((tog, obj.name))
                if obj.type == 'Mesh':
                        tog = Blender.Draw.Create(0)
                        popup.append((obj.name + ' (mesh)', tog))  
                        meshes.append((tog, obj.name))
        if not Blender.Draw.PupBlock("Attach mesh to armature? ", popup): return
        armatureName = ''
        for tog, name in armatures:
                if tog.val:
                        if armatureName != '': Draw.PupMenu("Duplicate armature")    
                        armatureName = name
        meshName = ''
        for tog, name in meshes:
                if tog.val:
                        if meshName != '': Draw.PupMenu("Duplicate mesh")    
                        meshName = name

        mesh_object = Object.Get(meshName)
        armature_object = Object.Get(armatureName)
        if mesh_object.getType()!='Mesh':
                result = Draw.PupMenu("You need a mesh")             
                return
        the_mesh = mesh_object.getData(mesh=1)
        print 'the mesh is at ', mesh_object.loc
        if armature_object.getType()!='Armature':
                result = Draw.PupMenu("You need an armature")             
                return
        the_armature = armature_object.getData()
        print 'the armature is at ', armature_object.loc

        editmode = Window.EditMode()   
        if editmode: Window.EditMode(0)   
        Window.WaitCursor(1)  

        if mesh_object.parent != None: mesh_object.clrParent()
        alignArmature(armature_object, mesh_object)
        armature_object.makeParentDeform([mesh_object])   
                
        if editmode: Window.EditMode(1) 
        Window.WaitCursor(0)
        Window.RedrawAll() 
  
            
if __name__ == '__main__':
   main() 

Besides fixing a few things* with the above script, I have tried again with the same mesh, ran the script again, but this time it ā€˜failed to find a solutionā€™. So I donā€™t know what to; forget about bone heat?

  • (You need to change
    diff = armatureLoc - meshLoc

to diff = meshLoc - armatureLoc

I think)

Hi, I got the same problem with that error message. I fixed it by turning on subsurf. DonĀ“t ask me why, but when you turn on subsurf the problem is solfed. After connecting the armature to the mesh you can just deactivate subsurfing and it works perfectly. :slight_smile:

6 Likes

Nice that worked for me too! Thanks.

Iā€™ve had this problem before 2.5 . my solution is to build deform bones in one layer, control bones in a separate layer and and use bone heat with only deform bones. I think you get this problem when you have for example eight bones in and around a foot but only two
deformer bones.

@Moritz
Probably why i (allmost) never have any bad issues with Bone Heatā€¦ Never do nothing with no Subsurf on!! :wink:

Try a ā€˜remove doubleā€™ before using bone heat.

I have tried all the recommendations on this track. Made sure my non side specific middle bones are exactly at the middle line. As for double checking and ensuring how perfectly mirrored my armature is. I did create it with X-mirror on, but I might have moved some bones on one side by turning the X-mirror off temporarirly. That is there could be very slight location mismatches between both sides. Or who knows I might have mistyped some of the bone names. I did not automatically generate 'em. Is there any kind of script that can check oneā€™s armature for symetry and use one side as the master and report on the mismatches it finds, and automatic fixes it makes?

I not only removed doubles, I ran ā€œclean meshesā€ script.

I tried enabling the Display of Subsurf that did not do it, I Applied it. Since I was not sure what you meant by ā€œTurning On subsurfā€.

Except this last recommendation

I did not try putting my deform bones in a separate bone group than my other bones. I kind of assumed the algorithm would check on the Deform flag of the bones as it seeks a solution. It sounded like 2.49b would need this work around, correct? My rig is not that sophisticated to have control bones outnumber deform bones. :wink:

I had the same problem and I fixed it by applying scale and rotation
from 3d window tool bar --> Object --> Apply --> Rotation & Scale
also I turned X-Axis Mirror off for the Armature

I had the same prob in Blender2.57, upgraded to 2.59 - same problemā€¦
My issue was the mesh.
I fixed it by selecting all > Mesh > Verticies > Smooth Vertex - then parenting the rig.

1 Like

Omg!! Thank you i stayed up until 3 A.M. the other day trying to solve this problem and I just tried your subsurface idea and it worked!!!

Bump! plz help! None of these solutions are working for me =( Iā€™m at a loss and donā€™t want to have to start all over on my model.