[Closed] Bone Mirrorring through MaxScript
Hi everyone, I’m trying to create a copy of a bone chain and then mirror it while flipping the Z axis. I found this in Maxscript Reference, but i haven’t been able to use properly. (sorry for the color of the text, it’s copied directly from Maxscript Reference)
Interface : INode[left].boneAxis : enum : Read|Write
[/left]
[left]boneAxis enums: {#X|#Y|#Z}
[/left]
[left]Gets/Sets the nodes Bone Axis.
[/left]
[left].boneAxisFlip : boolean : Read|Write
[/left]
[left]Gets/Sets the nodes Bone Flip Axis option.
[/left]
I’ve tried different things and none of them seem to work. Thanks for any help and have a good day.
(
--//-- $ is the root bone!
maxOps.CloneNodes $ expandHierarchy:true clonetype:#copy newNodes:&newnode
about $.pos scale newnode[1] [1,1,-1]
)
you may be able to do this with the bone interface but haven’t tried yet !
best regard,
martin
I would strongly advise against negative scaling a bonestring, for various reasons. I would gather the points from one side and build a new bone based on the -x coordinates.
so take a leftBone for example
lBone = selection[1]
sPoint = lBone.pos
ePoint = (preTransLate lBone.transform [(lBone.inode.stretchTM.scale.x *lBone.length),0,0]).pos -- get bone end pos, compensate for stretch
rBone = boneSys.createBone [-sPoint.x,sPoint.y,sPoint.z] [-ePoint.x,ePoint.y,ePoint.z] -lBone.dir
This will create a new bone with a flipped Z axis.
Hope this get’s you on the way, the best thing about this approach is that there’s no children or parent looping quering involved since we solved the length of the bone by itself using the preTranslate function.
-Johan
yes recreating the bone chain from scratch is the best solution but he will still need to iterate through the bone chain to find ik solver, if any !
Works just great! Thanks a lot man, it’s pretty awesome thing to be able to get help like that, I love these forum. One day, i’ll be good enough to return the favor to somebody else. Have a good one
I always create bone from spline with something like this …
(
RigName="rig"
--//--
fn CreateBones spln name dir color1 color2 Side front back taper width height =
(
local Xknot=(numKnots spln)
local GradColor=(color1-color2)/Xknot
local PrevKnot=undefined
local PrevBone=undefined
local b0=undefined
--//--
for f in 1 to Xknot do
(
Case f of
(
1:(
PrevKnot=(getKnotPoint spln 1 f)
)
Xknot:(
b0=BoneSys.createBone PrevKnot (getKnotPoint spln 1 Xknot) dir
b0.parent=PrevBone
)
Default:(
b0=BoneSys.createBone PrevKnot (getKnotPoint spln 1 f) dir
b0.parent=PrevBone
PrevBone=b0
PrevKnot=(getKnotPoint spln 1 f)
)
)
--//--
if b0 != undefined then
(
b0.name=uniquename (RigName+"_"+name+"_")
b0.wirecolor=(color1-(GradColor*f))
b0.sidefins=Side
b0.frontfin=front
b0.backfin=back
b0.taper=taper
b0.Width=width
b0.height=height
)
)
--//--
)
--//--
for f in selection do
(
CreateBones f "test" f.dir (color 255 0 255) (color 255 0 0) off off off 60 2 2
)
--//--
)
so if I want symmetry , I mirror the spline and recreate again
Hope this help,
martin
Hi guys,
i used JHN’s piece of code and it worked well to flip the axis of the bone. What i am realizing now is that the bone is flipped but it’s rotation isn’t exactly mirrored to the other side. There might be some logic that i’m not getting here. (sorry for putting the code like that, but i don’t know how to create that little Code window in the post). So here is a piece the code that i am using to create a new chain of bone that is flipped (using JHN advice thx a lot btw)
(
local
bnsM=#(),
i= 1
– Creates a Z flipped chain of bones of the leg
for b in selection do
(
flipBone= selection[i]
sPoint= flipBone.pos
-- get the position of the end of the bone (results in the position of the next bone in the chain)
ePoint= (preTransLate flipBone.transform [(flipBone.inode.stretchTM.scale.x *flipBone.length),0,0]).pos
mirBone = boneSys.createBone [-sPoint.x,sPoint.y,sPoint.z] [-ePoint.x,ePoint.y,ePoint.z] -flipBone.dir
append bnsM mirBone
i=i+1
)
-- Creates the hierarchy between the flipped bones
for i = 2 to selection.count do
(
bnsM[i].parent= bnsM[i-1]
)
)
I’ve attached this image to represent better my problem. If you look at the point helper on the left, he is mirrored with the point helper on the right (that is aligned with the original bone chain). My newly create bone chain on the left is positionned correctly, but the orientation is off.
If anybody knows what i’m doing wrong it would be of great help. Thanks a lot guys for the previous responses. Have a good one
Is that what your looking for?
just follow the instructions in the example part of the code to see it in action…
(
-- return the mirror of this point on a given axis
-- the axis argument can be 0 for X, 1 for Y or 2 for Z
-- any other value will simply copy the point
fn mirrorPoint pt axis =
(
pt * (
case axis of (
0: [-1,1,1]
1: [1,-1,1]
2: [1,1,-1]
default: [1,1,1]
)
)
)
-- return the end point of a given bone in world space
fn getBoneEnd bone =
(
[bone.length, 0, 0] * bone.transform
)
-- will copy the base object and wire color from one bone to another
fn copyBoneProperties fromBone toBone =
(
toBone.baseObject = copy fromBone.baseObject
toBone.wireColor = fromBone.wireColor
)
-- recursively mirror copy a chain of bones on a given axis
-- starting from the last bone and ending on the first bone in the hierarchy chain
fn mirrorBoneChain lastBone axis =
(
undo "Mirror Bones Script" on (
max create mode
local parentBone = undefined
if isKindOf lastBone.parent BoneGeometry then
parentBone = mirrorBoneChain lastBone.parent axis
local start = mirrorPoint lastBone.pos axis
local end = mirrorPoint (getBoneEnd lastBone) axis
local dir = mirrorPoint lastBone.dir axis
local newBone = boneSys.createBone start end dir
copyBoneProperties lastBone newBone
newBone.parent = parentBone
newBone
)
)
-- Example:
-------------------------------------------------
-- manually create a chain of bones and select the last bone in the cahin
-- this line will mirror copy the chain on the X axis:
mirrorBoneChain $ 0
-- this line will mirror copy the chain on the Y axis:
mirrorBoneChain $ 1
-- this line will mirror copy the chain on the Z axis:
mirrorBoneChain $ 2
)
or using some kind of hack from Zeboxx you can do something like this …
(
--//--
--//-- select a bone chain including ik and run the script.
--//--
fn XMirror =
(
local Xhwnd=dialogMonitorOps.getWindowHandle()
local Xstring=UIAccessor.GetWindowText Xhwnd
--//--
if Xhwnd != undefined then
(
if Xstring != undefined and (findString Xstring "Mirror") != undefined then
(
UIAccessor.PressButtonByName Xhwnd "X"
UIAccessor.PressButtonByName Xhwnd "Instance"
UIAccessor.PressDefaultButton()
)
)
true
)
--//--
if selection.count != 0 then
(
dialogMonitorOps.registerNotification XMirror id:#findmirror
dialogMonitorOps.enabled=true
--//--
max mirror
--//--
dialogMonitorOps.unregisterNotification id:#findmirror
dialogMonitorOps.enabled=false
--//--
Newselection=selection as array
--//--
for f in 1 to selection.count do (max select parent)
--//--
for f in selection do
(
InstanceMgr.GetInstances f &x
for i in x where (i != f) do f.pos.x=-i.pos.x
)
--//--
select Newselection
InstanceMgr.MakeObjectsUnique Newselection #group
)
--//--
)
witch will mirror bone chain and ik as well
best regard,
martin