Bone-to-bone driving relationships like that are problematic if the bones are in the same armature – it’s a form of cyclic dependency that can cause erratic behavior – and afaik Constraints won’t work in that situation, either.
I did something very similar in my rig for the Kata character (rotation values driving other bone transforms) before I learned about this, and have recently switched to using a separate armature to provide the values that drive the main armature. Both armatures use the same Action and are identical in terms of the relevant bones. I use a pydrivers.py script to set up the formulas for each driven bone. You can search this site and the web for info on pydrivers.py scripts. Some BPython knowledge is required. The basic premise is that instead of an IPO curve, the transform channel in the IPO Editor is driven by values returned from functions in the pydrivers.py script.
When I assign the bones translation in Z to do the rotation in Z it works fine. But, I just told X to drive Z and it breaks, :-\
– EDIT –
I figured it out, I am using another armature to drive it now. I made the Z Channel the X channel and now it works fine. We should document this clearly.
It’s still not consistent–my knowledge of BPython is not non existent.
This shouldn’t be this hard to do, this is disappointing.
– Another Edit –
It works if I make the bone rotate to drive the other bones rotation… hmmm.
– And another edit –
Solution found, I rotated the bone so that when I translate it accross what used to be the X axis, it’s now the Z, and it drives the heel properly now.
Good to know that the separate armature workaround applies to Constraints as well as pydrivers.py scripting. I agree that it’s unnecessarily complex to have to use 2 armatures, but it’s the nature of the Blender beast as it now exists – the depsgraph in particular, which is a bit of arcanity I’m only barely familiar with, but which makes such bone-to-bone dependencies less than reliable if in the same Armature.
BTW, the pydrivers.py scripting need not be hugely complex (mine is but that’s because I was trying something way beyond my depth, and I’m stubborn ), even simple expressions (e.g., equations) can be used. The main difficulty I found was learning how to identify a particular bone and its “absolute” rotation values (most rotations are relative to one space or another, which is reflected in Constraint settings as well) so the values could be used in expressions/equations. But for your purposes the Transform Constraint looks to do the job very well – afaik it didn’t exist when I started the Kata project, so I had to use other means.
Hope we’ll get some step by step tut with some examples of rotation constraints…
In the meanwhile, i guess i’ll have to animate my six leged sheep in a very artisanal and un-mathematic way… ;o/
But you say this is relatively easy though? Maybe I should learn it, I knew some MEL scripting before. Can’t be that different. This is complicated but i am falling in love with rigging.
You don’t happen to have a good solution for lat muscle deformation do you?
I don’t really consider any of my rigging solutions as anything more than adequate. I’ve automated a number of “helper” bones (sometimes called “fan” bones, I think) using the pydrivers.py approach, but just as often use manual adjustments in places like the lats, deltoids, upper traps, breasts, and a couple of other areas that didn’t lend themselves well to automation, usually using unconnected bones much as is done with facial rigs. I don’t get perfect deformations, mainly due to some modeling faults, but it’s good enough for my purposes, and simple enough that I don’t go total berkers animating with it. Here’s an early pic from the WIP thread with the bones supered on the ghosted wires:
It’s still pretty much the same, a number of refinements since then but the essentials are there.
I haven’t done all that many figures ‘n’ rigs, so I’ve learned a lot about the shortcomings I built into the Kata model and armature. For the most part, I’ve found that modeling for successful deformation in problem areas like the shoulders is an essential step, which means a lot of testing & revision before starting animation.
I saw that you’ve found a working solution, but I just thought I would take a moment to explain this constraint because I struggled with it in the same way. Your problem is not a dependency cycle, it is perfectly allowed. Heck you can even use the transformation constraint between a parent and it’s child! It’s pretty powerful stuff!
In the left column as you know, the values are consistently X, Y, Z from top to bottom. The exact same is true for the right column. If you want to map one value to another, you use the rollout menu to assign one channel to another. And if you ever want to use a negative value, enter the negative number as the min, not the max.
For your setup it should look something like this:
@ fgc – so the Transformation Constraint has no dependency limitations? Can the target of one Trans’n constraint point back to the constrained object with another Trans’n constraint (the classic dependency arrangement)? Or does this only apply to bones within the same armature? I’m interested because I wonder, if this can be done with a Constraint, why does using a pydrivers.py script in similar fashion (bones driving bones in the same armature), cause depsgraph-related errors? That’s a rhetorical question of course, but it seems these are similar situations, and if one can be “fixed” then it sounds logical that both can.
Though in some ways it seems the Transformation constraint may have been designed to replace certain functions that a pydrivers.py script was capable of, but with the bonus of the constraint being simpler to implement.
Well I didn’t mean that it has no limitations - a cyclic setup will always be a dependency cycle. Constraining the driver with the constrained will be a dependency, as will making a child bone drive it’s parent (which makes sense, and you would never want to do that anyway since it would be impossible to control). But a parent can drive it’s child without any apparent problem.
I do find it interesting that the message returned by the console when a transformation constraint setup is cyclic is ‘Bone depends on Bone.001 through IK constraint’ when I have no IK constraints…
I was under the impression that that applied to bones driving bones in the same armature, because the depsgraph evaluated the Armature as a node (depsgraph node, that is), and thus the status of that node was internally dependent on itself. Maybe not a clear impression, but it has been commented on a number of times that this can induce a kind of “lag” in the rendering process. For my Kata rig, before using a dupe Armature as the source for pydrivers data, that meant the pydrivers values weren’t updating properly when I used the ANIM button to render a sequence. Initially I fixed that with a script that called the RENDER button operation for every frame, which for some reason fixed the issue. Then I got the idea of a dupe armature from another ba.org thread (such a great resource!) and that was the better fix, the ANIM button works right now.
So, somehow, it seems the Transformations Constraint avoids that particular depsgraph problem. If I’m understanding this properly, which is always a question. “Gettin’ too old for this s**t!”
oh I think I see what you’re getting at now. Yea, directly driving the IPO of another bone in the same armature is not allowed. So dual armatures are needed for that kind of setup, you are correct. The transformation constraint as I understand it simply maps one value onto another. So the hierarchy doesn’t really come into play, bone A has a value change and moves one way, so bone B is given a value change and moves the other. So long as the value change itself is not dependent (for example the value of bone B effects the value of bone A, and back to B), or the use of the constraint does not create a similar dependency through a series of constraints, it will work fine.
I would think that constraining the child to the parent might be a dependency but it isn’t because blender is just mapping the values, the parent goes one way and so the child goes the other. But of course it becomes a dependency if the child controls the parent because the parent determines the position (values) of the child.
Can’t say as how I see much difference, other than semantic, between “mapping” a value from one bone to another and “driving” a bone with values obtained from another bone. In my pydrivers.py setup, I obtain a value from one bone’s rotation axis, modify it with a little math magic, and return a value that is used in one of another bone’s transform channels. That looks a lot like what the Transformation constraint does, though with perhaps less complex math modulating the source data. In either case the state of one bone directly affects the state of another. One method is “allowed,” the other isn’t, but why that should be so isn’t that clear to me.
I think the semantics are important here, because the two approaches could be viewed differently.
If you were to drive a bone directly you would be connecting those bones together in a sense. Connecting the driving channel of one with the driven channel of the other.
When using the constraint, since it deals with just the values, no direct connection is needed. The constraint likely checks the driver bone for a value change, and if it has changed, it updates the value of the constrained bone. The constraint would basically serve as a mediator, avoiding any dependencies since no actual ‘connection’ is needed.
That’s exactly what my pydrivers.py script does. I think you’re right in that there is a difference, but I think it’s because the constraint does not (apparently) use an IPO channel and the script does. The constraint approach is “immune” to generating a certain type of depsgraph error, while the pydrivers.py method is not, even though they accomplish the same ends. It may be that the script-driven-channel approach cannot be given this “immunity” due to some code configuration the constraint was specifically designed to circumvent – only the devs know for sure :). But functionally the two approaches are identical. Make “black boxes” out of the processes and you wouldn’t be able to tell the difference between them other than in secondary effects, i.e., the depsgraph-related errors.
So what if you wrote a pyconstraint instead of a pydriver to control the bone? Would that give you access to the same behaviour as the transformation constraint? Or would that behaviour not be something the pyconstraint could do? (I’ve only started looking into rigging scripts, but I can’t wait to learn them because it seems like the possibilities really open up when you know how to use them fully )
Don’t know pyconstraints, either, they were something that also materialized well after I had begun the Kata project. But from what I’ve heard about them they do seem to offer a good solution for a lot of otherwise hairy probs – too late to adapt the Kata rig at this point but definitely a resource for future rigs.
The thing about the pydrivers.py scripted approach is that it seems so clean: a bone is transformed (a frame change also), and this calls a function in the script that delivers a value to another bone. All the functions are “centrally located” in the script, which can be open in the Text Editor for easy adjustment. No need to access and tweak individual Constraints on individual bones.
That I get, but for some reason in my rig, it will only work if it’s Z to Z directly, no changing of the channels. But in a blank file, it works fine. Go figure.
Also:
This actually works–so what the heck is going on?
The movement of the driver bone for 1.9 units in local Z produces a scale from 1 to 0.4 in the local Y axis of the constrained bone (perhaps max values can be negative). If you wanted to scale the bone uniformly you could make all the rollouts read Z…
But I’m not really clear on what you’re trying to achieve with the constraint, so it is hard to offer feedback… a screenshot of how this constraint is implemented on your rig would help