Notifications
Clear all

[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 node’s Bone Axis.
[/left]
[left].boneAxisFlip : boolean : Read|Write
[/left]
[left]Gets/Sets the node’s 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.

14 Replies

(
--//-- $ 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

 JHN

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

Sorry, but i wasn’t able to attach the jpg to the previous post.

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

Page 1 / 2