G'day,
Just wondering if anyone knows any good ways to mirror character poses for limbs?
I'm just having to manually do it all the time and it feels like there must be a better way.
Any ideas?
Thanks,
Pete
Mirroring Posses
6340 14 5-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
-
- goldfarb
- Staff
- 3464 posts
- Joined: July 2005
- Online
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
-
- goldfarb
- Staff
- 3464 posts
- Joined: July 2005
- Online
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
Hey I got something working!

Made a little button out of this script -
Objects have to named with R_ or L_ for it to pick up on them.
Next I'm going to try and save that to disk so I can copy a pose from one frame and paste to another.
P.

Made a little button out of this script -
def MirrorObject(InputName): FoundOpposite = False if "L_" in InputName: OpposideSide = InputName.replace("L_","R_") FoundOpposite = True if "R_" in InputName: OpposideSide = InputName.replace("R_","L_") FoundOpposite = True if FoundOpposite == True: #Store the Opposite Side OppositeObj = hou.node(OpposideSide) #Store Current Side thisSide = hou.node(InputName) #Rotations if OppositeObj.parm("rx").isLocked() == False: OppositeObj.parm("rx").set(thisSide.parm("rx").eval()) OppositeObj.parm("ry").set(thisSide.parm("ry").eval()) OppositeObj.parm("rz").set(thisSide.parm("rz").eval()) #Transforms if OppositeObj.parm("tx").isLocked() == False: OppositeObj.parm("tx").set(-thisSide.parm("tx").eval()) OppositeObj.parm("ty").set(thisSide.parm("ty").eval()) OppositeObj.parm("tz").set(thisSide.parm("tz").eval()) #Mirror the selected bones for node in hou.selectedNodes(): path = node.path() MirrorObject(path)
Objects have to named with R_ or L_ for it to pick up on them.
Next I'm going to try and save that to disk so I can copy a pose from one frame and paste to another.
P.
Edited by peteski - Sept. 5, 2016 20:49:09
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
Okay I got the save to disk working! So now I can store a pose and restore it at another frame (mirrored or not). It's super handy! It might break, but I thought I'd post it anyway incase anyone else (or future me) need it. Arctor, maybe if you have a sec, could you have a quick look at the code, just in case I'm doing something obviously stupid 

Store the currently selected object's poses -
Restore the same pose -
Restore the pose Mirrored -


Store the currently selected object's poses -
#Store all Currently Selected Objects ValuesToSave = "" for node in hou.selectedNodes(): #Node Path ValuesToSave += node.path()+',' #Rotation ValuesToSave += str(node.parm("rx").eval())+"," ValuesToSave += str(node.parm("ry").eval())+"," ValuesToSave += str(node.parm("rz").eval())+"," #Transform ValuesToSave += str(node.parm("tx").eval())+"," ValuesToSave += str(node.parm("ty").eval())+"," ValuesToSave += str(node.parm("tz").eval())+"\n" #Save to disk SaveFile = hou.hscriptExpression("$JOB")+'TempPose.txt' file = open(SaveFile, "w") file.write(ValuesToSave) file.close()
Restore the same pose -
#Read the transforms from disk and Restore to selected objects StoredFile = open(hou.hscriptExpression("$JOB")+'TempPose.txt',"r") LoadedValues = StoredFile.readlines() for Line in LoadedValues: LineSplit = Line.split(",") TargetItem = hou.node(LineSplit[0]) #Load Rotations try: TargetItem.parm("rx").set( float(LineSplit[1]) ) TargetItem.parm("ry").set(LineSplit[2]) TargetItem.parm("rz").set(LineSplit[3]) except: pass #Load Transforms try: TargetItem.parm("tx").set(LineSplit[4]) TargetItem.parm("ty").set(LineSplit[5]) TargetItem.parm("tz").set(LineSplit[6]) except: pass """the try is there to avoid issues with permissions on some parameters"""
Restore the pose Mirrored -
#Read the transforms from disk and Restore to selected objects StoredFile = open(hou.hscriptExpression("$JOB")+'TempPose.txt',"r") LoadedValues = StoredFile.readlines() for Line in LoadedValues: LineSplit = Line.split(",") TargetItem = hou.node(LineSplit[0]) MirrorMultiplier = 1#This is used to flip the rotations in certain cases #Check for opposite side FoundOpposite = False if "L_" in LineSplit[0]: OpposideSide = LineSplit[0].replace("L_","R_") FoundOpposite = True if "R_" in LineSplit[0]: OpposideSide = LineSplit[0].replace("R_","L_") FoundOpposite = True if FoundOpposite == True: #Change the target item if the opposite item was found TargetItem = hou.node(OpposideSide) #If there was no opposide set the mirror multiplyer to mirror this bone if FoundOpposite == False: MirrorMultiplier = -1; #This is a really hacky way of differentiating between objects that should have mirrored rotations... try: TargetItem.parm("tx").set(0.0) MirrorMultiplier = -1; except: pass #Load Rotations try: TargetItem.parm("rx").set(float(LineSplit[1])) TargetItem.parm("ry").set(float(LineSplit[2])*MirrorMultiplier) TargetItem.parm("rz").set(float(LineSplit[3])*MirrorMultiplier) except: pass #Load Transforms try: TargetItem.parm("tx").set(-float(LineSplit[4])) TargetItem.parm("ty").set(LineSplit[5]) TargetItem.parm("tz").set(LineSplit[6]) except: print ("Transform Not Active"); pass
Edited by peteski - Sept. 6, 2016 00:34:46
-
- matthias_k
- Member
- 483 posts
- Joined: Dec. 2006
- Offline
-
- goldfarb
- Staff
- 3464 posts
- Joined: July 2005
- Online
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
Hey I managed to get the scripts working on a parameter level
(thanks @tamte for the help getting interface buttons workin'!)

It's a lot cleaner really and it looks like it can handle other parameters (like IK blend and such).
I'm just trying to figure out how to add things to a list now so I could perhaps store poses and stuff. Seems like it might be doable with ordered list?
P.

(thanks @tamte for the help getting interface buttons workin'!)

It's a lot cleaner really and it looks like it can handle other parameters (like IK blend and such).
I'm just trying to figure out how to add things to a list now so I could perhaps store poses and stuff. Seems like it might be doable with ordered list?
P.
Edited by peteski - Sept. 28, 2016 04:38:27
-
- goldfarb
- Staff
- 3464 posts
- Joined: July 2005
- Online
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
Hey I had a mess with the pose library but I wanted to add a few things so I finished off the script I was working on and it's working pretty cool!
Figured you might like a look?
Here's the hand, also a pose stored on left or right can be restored from the other side.

The whole thing mirrors too! (That is a tiny bit slower)

I realised I could use this for saving and loading rig variations too

On to Animating some stuff
P.
Figured you might like a look?
Here's the hand, also a pose stored on left or right can be restored from the other side.

The whole thing mirrors too! (That is a tiny bit slower)

I realised I could use this for saving and loading rig variations too


On to Animating some stuff

P.
-
- Felix6699
- Member
- 45 posts
- Joined: Aug. 2012
- Offline
-
- peteski
- Member
- 522 posts
- Joined: Dec. 2013
- Offline
Hey thanks Felix,
It took a little while to get my head around but thankfully Python is so widely used that for any general question, you can just do a quick search online and you'll find an answer. For the more Houdini specific stuff I just keep a bookmark of the reference ( and hassled a lot of the good people here
).
This isn't bad for an into tute - https://www.youtube.com/watch?v=GubmnSEyKS8 [youtube.com] it goes over some of the basic things you can do with it pretty easily.
Also the docs are actually quite good, http://www.sidefx.com/docs/houdini15.5/hom/_index [sidefx.com]
I'll post up a little example file soon and you can look through that.
Pete
It took a little while to get my head around but thankfully Python is so widely used that for any general question, you can just do a quick search online and you'll find an answer. For the more Houdini specific stuff I just keep a bookmark of the reference ( and hassled a lot of the good people here

This isn't bad for an into tute - https://www.youtube.com/watch?v=GubmnSEyKS8 [youtube.com] it goes over some of the basic things you can do with it pretty easily.
Also the docs are actually quite good, http://www.sidefx.com/docs/houdini15.5/hom/_index [sidefx.com]
I'll post up a little example file soon and you can look through that.
Pete
-
- Felix6699
- Member
- 45 posts
- Joined: Aug. 2012
- Offline
Yep… Actually Python language is very easy to understand. At given instant of time it became very popular in the world and a lot of information you can get. But in Houdini, this language is used as binding element. If you do not know the functions HOM and how they work - is a headache. Also, for the code editor, inconvenient to receive feedbacks and others issues. You can spend a lot of time to finally understand where you're wrong. This video tutorial I already looked. Perhaps this is the foundation to begin to do something. However, this is not enough to do something more complex
. Thank you can share your code. It helps in understanding how some things are work.

-
- Quick Links