Copying Parent-Relative Positions from one Object to Another in Blender

Well, the title of this post sure is a mouthful... but try as I might, I just couldn't come up with a shorter way to phrase what I've been doing and am going to write about here!  I've been working on a proxy model for the Blood Imp monster from Gloomhaven: Jaws of the Lion.  There has been a terrible heat wave in California though with rolling brown-outs in my area due to the increased draw on the electric grid caused by everyone's AC units.  Given that we've all been suffering from power shortages, it just doesn't seem responsible to fire up the printer and put more stress on the system.  Also, because this model is only a head and 4 limbs and reposing it isn't as much work as it would be for a normal humanoid creation, I figured that I could make a few alternative poses for it while I wait out this heat wave to begin test printing!

So, I made my first pose, copied it off to a new collection, then began work on another pose.  It wasn't until I'd done quite a lot of work on the new pose (and overwritten my file) that I realized that I'd made a mistake.  See all of those giant teeth?  Well, I tried to get clever while making them.  I sculpted one tooth, then used an Array modifier to make a bunch of copies of it.  To give me better control of the spacing of the tooth instances, I set the array's offset to be based on the position of an Empty relative to the fang itself.  By not only translating the position of that empty, but also by rotating and scaling it, I was able to both bend the path of the array and shrink the teeth as they went further towards the back of the creature's mouth.

Well, the Fang array was working great, but I put the Empty objects in a different collection so that I wouldn't accidentally select them and mess things up while working on other stuff.  When I copied the model onto my "ForPrinting" collection, I forgot to copy the Empties, which meant that my backup copy's teeth were still being defined by the Empties that I was going to be moving around for the new pose (in my Workspace collection).  After finishing the first draft of the new pose, I wanted to compare it to the original... and was unhappy to find a flying aura of fangs around my monster!

D'oh!  Now I've got a bit of a problem on my hand.  I need a new set of Empties for this pose, and I need to get their exact position/rotation relative to this pose's fang objects to match the Empties' positions/rotations relative to the new pose's fang objects (ugh, yep, still difficult to verbalize what I'm trying to say here...).  While it's simple enough to copy the Workspace Empties over to this Pose Collection, getting them in the precisely right spots to get the teeth to line back up with the gums would be incredibly difficult by hand.  I could always remove all of the parenting, then look at the differences between the fang's XYZ position and rotation data and the empty's XYZ position and rotation data, then do the math based on the Pose Collection's fang's XYZ position and rotation data to figure out the new positions that I need for the empties... but that process is sufficiently complicated that I'm not even 100% sure that I just explained it accurately, must less that I could go through it without making all sorts of silly math and logic errors.  Also... this isn't the first time that I've gotten myself into a situation like this, so I figured that it was time to come up with a real solution.

Well, a bunch of google searches and experimentation yielded results (I mean, why else would I be writing about it here, right?)!  The answer was to use Blender's Python console, which is a bit intimidating, but is ultimately not too difficult to use (at least, for simple things like this).  Just as Blender is an object oriented modelling tool, its command line console is similarly object oriented.  That means that each model object (for example, a fang) has a whole bunch of properties that can be accessed at the command line.  After a bunch of research, I realized that the .mesh_local property contained the exact data that I needed in this situation.

An object's .mesh_local property expressed its location, rotation, and scale relative to its parent object.  So, that means that the solution to my problem is actually really simple.  I need to find the mesh_local value for the Workspace Empties (which are working great with the Workspace Fangs), and I need to put that value onto the Pose Empties (which are all kinds of messed up in regards to the Pose Fangs).  In my case, the Pose instances of the objects are all named with a .001 suffix (since they're copies of the Workspace instances).  That means that the console command to copy the Workspace instance's values over the Pose instance's values is: bpy.data.objects['Empty.Fangs.Lower.001'].matrix_local = bpy.data.objects['Empty.Fangs.Lower'].matrix_local

So, I copied my Empty objects over to the Pose collection, parented each one to its appropriate Fang object, and changed my Array modifiers to use these new Empties.  Then, I changed over to the Scripting workspace in Blender (I suddenly appreciate the problem of naming my primary collecting "workspace" given that the term has other meanings in Blender).  In the middle-left Console window, I ran that command (and its Upper fangs equivalent).  And that was it!  Once I overwrote the matrix_local values on my messed up empties with the values from my working empties, everything just came right together!


So, there you have it!  If you ever need to copy the relative position between an object and its parent over to another object and its parent, it turns out there's a really easy way to do it!  When it comes right down to it, I think that it's probably even easier to do it than it is to describe what it is that you're doing!

Comments

Popular posts from this blog

How Much Filament Do I Have Left

Prusa MK3 Stringing at .05 mm Layer Height Resolved!

Using PrusaSlicer to Design Tree Supports for FDM Prints