Reducing rig bone counts

I would like to know if there is a workflow to at least semi-automatically reduce an already rigged model to a version with a simpler rig.

The main reason for this is that I want to prepare models for exporting to Ogre3D mesh format, which only allows a maximum of 256 bones (limiting bone counts is not such a bad idea in realtime render engines).

When rigging meshes with rigify, even though the human meta-rig has only 63 bones, clicking “Generate” will result in an armature with 333 bones, which is already too much. Can someone maybe explain what exactly happens there?

So, basically I’d like to know if there’s a good way to quickly rig a simple biped armature to a human character that was already rigged with a more complex armature, without needing to redo all the weight painting.

Rigify creates many layers of bones: deforming bones, FK bones, IK bones. If you aren’t working on delicate animation you can get away with deforming bones only (so don’t click “Generate” from within Rigify, or if you already did then go back in and delete out the non-deforming bones).

Something like that.
-rking

Reducing the number of bones of an already rigged and skinned character will be complicated but, indeed if you can delete all bones except the deformation bones without breaking the rig, this should work.
Starting with only the deformation bones, here’s a good tuto to get and efficient rig with a few extra bones.

Thanks,
reading this and searching the net gave me a little better understanding of it.

Apparently, someone made a script that does something similar: http://forum.unity3d.com/threads/90913-Rigify-to-Unity
Unfortunately it is not a blender script (I think).

I wonder what bones this script removes exactly and how (or if) it manages to leave an arbitrary rigify rig intact.
It would be nice to reproduce a similar thing as a Blender script.

ORG_PREFIX = “ORG-” # Prefix of original bones.
MCH_PREFIX = “MCH-” # Prefix of mechanism bones.
DEF_PREFIX = “DEF-” # Prefix of deformation bones.
WGT_PREFIX = “WGT-” # Prefix for widget objects

These seem to be the naming conventions rigify uses for its bones, so I guess these are all the types of bones rigify uses.

Thank you for the tutorial, by the way. I only have limited experience with rigs so this really helps.

mmm, and why don’t export only deformation bones?? the are aprox 40, even less if you don’t export the palms and all the fingers

I was experimenting with the Flick model to explore rigify rigs some more.
I tried to export her to Ogre as an experiment, but she had quite a lot of bones, and at first I was quite overwhelmed by the amount of layers, couldn’t find all bones or remove some of them etc.

Eventually I discovered how it works, and must say I’ve learned a lot. I ended up removing all non-deformational bones manually (which were a lot), which still left me with 156 deforming bones (but under the 256 maximum, so it worked).
I must say, without those helper bones it’s become quite hard to pose her, especially the face rig.

By exporting, what do you mean exactly? Deleting the unwanted bones like I did, or is there a faster way?

i have using rigify for a while, and what i’d do is to modify the exporter script. in this case, i have written one to myself. so, i only export the bones in one specific layer of the armature. i can have all the bones i want to help animator, but only a couple of them are exported to the engine. i don’t know how the ogre3d exporter works, but i wonder you could do the same.

That’s a good idea! Thank you for the tip.
I don’t think it has this feature (yet) but it could be added. It’s a python blender addon so it’s easily modifyable. But I will suggest it to the developer.

When doing an animation by moving one of those “helper” bones, you would just have to make sure that the effect on the actual deform bones is keyframed, right? For example, posing the rig, selecting all bones and adding a keyframe for them would do the trick?

For reference, the Ogre exporter I’m using is blender2ogre (http://code.google.com/p/blender2ogre/)

Probably the easiest thing to do is learn how to rig. Rigify is a very complex and nice rig, but you have to ask yourself if you really need all that functionality for your game characters. Personally I liked the mancandy faq a lot, which you can find online, but at this point it may be dated and confusing if you weren’t a 2.4x user. Plus you would need to look elsewhere for a ik/fk switcher for the arms.

I come from blender 2.4 (in fact I’m still getting used to 2.5) but never really went into detail with rigging, at least not further than some basic stuff. Learning more about rigging is probably a good idea. Thank you for the tip on the FAQ, I’ll have a look at it.

That’s correct. The script is for Unity and implemented in C#, but open source! Just ask me if there are things you don’t understand.

// Author: Andreas Suter
//
// Copyright (C) 2011 by Edelweiss Interactive (http://www.edelweissinteractive.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public class RigifyToUnity : AssetPostprocessor {
    
    /// Warning: Several code lines removed here!

    protected void OnPostprocessModel (GameObject a_GameObject) {
        
        if (a_GameObject.name.ToLower ().Contains (NameFilter.ToLower ())) {
            
                // Needed game objects.
            
            HashSet <GameObject> l_NeededGameObjects = new HashSet <GameObject> ();
            l_NeededGameObjects.Add (a_GameObject);
            
                // All meshes are needed, except for the ones that are used as bone shapes in Blender.
            foreach (MeshRenderer l_MeshRenderer in a_GameObject.GetComponentsInChildren <MeshRenderer> ()) {
                if (!l_MeshRenderer.name.ToLower ().StartsWith (BoneShapePrefix.ToLower ())) {
                    l_NeededGameObjects.Add (l_MeshRenderer.gameObject);
                } else {
                        // Game object is going to be deleted later. But we already destroy the mesh.
                    MeshFilter l_MeshFilter = l_MeshRenderer.GetComponent <MeshFilter> ();
                    if (l_MeshFilter != null && l_MeshFilter.sharedMesh != null) {
                        Object.DestroyImmediate (l_MeshFilter.sharedMesh, true);
                    }
                }
            }
            
                // All skinned meshes are needed.
            foreach (SkinnedMeshRenderer l_SkinnedMeshRenderer in a_GameObject.GetComponentsInChildren <SkinnedMeshRenderer> ()) {
                l_NeededGameObjects.Add (l_SkinnedMeshRenderer.gameObject);
                foreach (Transform l_BoneTransform in l_SkinnedMeshRenderer.bones) {
                    l_NeededGameObjects.Add (l_BoneTransform.gameObject);
                }
            }
            
                // All game objects that contain 'ExceptionBones' in the name are needed.
            foreach (Transform l_Transform in a_GameObject.GetComponentsInChildren <Transform> ()) {
                if (l_Transform.name.ToLower ().Contains (ExceptionBones)) {
                    l_NeededGameObjects.Add (l_Transform.gameObject);
                }
            }
            
                // All parents of the needed game objects can not be deleted.
            List <GameObject> l_NeededGameObjectsWithoutParents = new List <GameObject> (l_NeededGameObjects);
            foreach (GameObject l_NeededObject in l_NeededGameObjectsWithoutParents) {
                Transform l_Transform = l_NeededObject.transform;
                while (l_Transform.parent != null) {
                    l_Transform = l_Transform.parent;
                    l_NeededGameObjects.Add (l_Transform.gameObject);
                }
            }
            
            
                // Not needed game objects.
            
            HashSet <GameObject> l_NotNeededGameObjects = new HashSet <GameObject> ();
            foreach (Transform l_Transform in a_GameObject.GetComponentsInChildren <Transform> ()) {
                l_NotNeededGameObjects.Add (l_Transform.gameObject);
            }
            l_NotNeededGameObjects.ExceptWith (l_NeededGameObjects);
            
                // Delete not needed game objects as long as the set is not empty.
            while (l_NotNeededGameObjects.Count != 0) {
                List <GameObject> l_NotNeededGameObjectsForLoop = new List <GameObject> (l_NotNeededGameObjects);
                foreach (GameObject l_NotNeededGameObject in l_NotNeededGameObjectsForLoop) {
                    if (l_NotNeededGameObject.transform.childCount == 0) {
                        l_NotNeededGameObjects.Remove (l_NotNeededGameObject);
                        Object.DestroyImmediate (l_NotNeededGameObject, true);
                    }
                }
            }
        }
    }
}

you could bake the animation to the deformation bones and remove all the other bones. then, of course, you couldn’t modify animation with that rig. you would have to save a copy of the file, of course, and repeat the same process for each change in animation

That’s the reason why I have implemented Rigify to Unity. In Blender I can just use Rigify as intended without deleting anything. As soon as it is imported to Unity all the unneeded stuff gets deleted automatically and what you get is a cleaner bone hierarchy.

Thanks for the insight in this matter.
Your idea for the importer seems the right one.
Alternative you could probably include the rig simplification code in your blender exporter so that it gets converted on the fly when it’s being exported, while keeping the original blend file intact.

I though of that too, but in my opinion it was not optimal. Unity automatically imports .blend files and internally uses Blender’s fbx exporter. Including simplification code in an exporter is not a very good idea, so having it in Unity directly was the best choice in my opinion.

Yes of course, if Unity itself already imports blend files than that’s a totally different matter.
I was referring to a case where you would have an export plugin in blender for a specific format that your render engine supports, like it’s the case with Ogre3D.