Notifications
Clear all

[Closed] Aligning bones and getting inverted scales

Hey all.

I’ve got a function which basically takes 3 bones and then effectively adjusts their twists so the rotations are planar.

Unfortunately, although these now look ok from a rotation perspective, the first and final bones get their scales inverted which obviously is bad. I’m sure I’m overlooking something really obvious here, but I can’t figure out what it is! So any suggestions would be very welcome!

My script is as follws (the bones in bonelist are parented from top to bottom)

boneList = #(
$bone1,
$bone2,
$bone3
)

axisorder = #(“x”,“y”,“z”)

/
Take 3 bones and create a plane between them
Use cross products to align the bones to that plane

/
fn alignBoneToPlane bonelist axisOrder =
(
theProjPlaneCoords = #(bonelist[1].pos, bonelist[2].pos, bonelist[3].pos)
initialTransforms = #(bonelist[1].transform, bonelist[2].transform, bonelist[3].transform)

-- Create a visible trimesh for this 
(
	vismesh = mesh vertices:theProjPlaneCoords faces:#([1,2,3]) materialIDS:#(1)
	vismesh.name = ("VISMESH_"+boneList[1].name+"_"+boneList[2].name+"_"+boneList[3].name)
)	

-- Get alignment of first bone. 
-- ASSUMING X, Y, Z FOR NOW!
-- X DOWN!
-- Y INTO THE PLANE!


-- Get a vector from bone 1 to bone 2. 
xVector =  bonelist[2].pos - bonelist[1].pos
xVector = normalize (xVector)
-- Get a temp plane vector from bone 1 to bone 3. 
-- Use this to find a cross vector that we'll discard
-- With that temp vector we find a proper 3rd vector, plus the correct second vector
tempVector =  bonelist[3].pos - bonelist[1].pos
tempVector = normalize (tempVector)
zVector = normalize (cross xVector tempVector)
yVector = normalize (cross xVector zVector)

finalTransform = matrix3 xVector yVector zVector bonelist[1].pos

bonelist[1].transform = finalTransform

bonelist[2].transform = initialTransforms[2]	

-- Get a vector from bone 2 to bone 3. 
	
xVector =  bonelist[3].pos - bonelist[2].pos

xVector = normalize (xVector)
	
zVector = normalize (cross xVector tempVector)
yVector = normalize (cross xVector zVector)

finalTransform = matrix3 xVector yVector zVector bonelist[2].pos

bonelist[2].transform = finalTransform
bonelist[3].transform = initialTransforms[3]

)

7 Replies

[i]– Take 3 bones and create a plane between them…

[/i]hmm 3 bones means 4 points. how can they be on the same plane for sure?

Sorry thats a mis-type in the comment there. I mean tri not plane

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

i think you want to align bones to their common plane… here is a solution. hopefully i didn’t forget anything

the function…


 fn planarPairBones bones = 
 (
 	tm1 = bones[1].transform
 	tm2 = bones[2].transform
 
 	v1 = normalize tm1[1]
 	v2 = normalize tm2[1]
 	up = normalize (cross v1 v2)
 
 	bones[1].transform = prescale (matrix3 v1 (cross v1 up) up tm1.pos) tm1.scale
 	bones[2].transform = prescale (matrix3 v2 (cross v2 up) up tm2.pos) tm2.scale
 	ok
 )
 

an example…


 delete objects
 (
 	b1 = boneSys.createBone (random [-40,-40,-40] [40,40,40]) (v2 = random [-40,-40,-40] [40,40,40]) z_axis
 	b2 = boneSys.createBone v2 (random [-40,-40,-40] [40,40,40]) z_axis 
 
 	b1.wirecolor = yellow
 	b2.wirecolor = green
 	b2.parent = b1
 	planarPairBones #(b1,b2)
 ) 
 

Are you coming from a Maya bone orienting/rigging paradigm?
Max bones != Maya bones, and certain “crucial” things about bone orientation in Maya do not necessarily apply in Max. I spent a lot of time fighting Max’s bones to try to accomplish Maya style orienting and in the end I abandoned it (because of wacky scale inversions.)

Paul Neale has a deep understanding of this issue.

Hrm… I’m not consciously coming from a ‘Maya centric’ approach. I can’t really say if I am inadvertantly though as its about 12 years since I last used it!

All I’m trying to do is orient my joint so that it is aligned with its parent, so that when i rotate it, it is not introducing twist – effectively I’m wanting to ensure my joint works like a hinge.

transforms and Matrix 3 values are tricky…
perhaps you can store the tranform.scalepart of each and reapply after the operation, to reset the scale back .

it seems like a complex method to get what you want -if i understand the problem.
if you hinge-like behavior always on, why not just lock the rotation on all axes but y or z?
if you want bones 2 and 3 to match bone1’s x and z (or x and y) rotation you can just convert .rotation too euler values and swap x and z (or x and y, which ever you are seeking)


--change quaternion to euler to get at xyz angles
bone1EulerRot=$Bone001.rotation as eulerangles 
bone2EulerRot=$Bone002.rotation as eulerangles

--make new euler rotation using bone 1 x and y, bone2 z
bone2EulerNewRot=eulerAngles bone1EulerRot.x bone1EulerRot.y bone2EulerRot.z

--convert the new euler rotation to a quaternion
bone2QuatRot= eulerToQuat bone2EulerNewRot

--set the rotation of$ bone002
$Bone002.rotation = bone2QuatRot


Thats great thanks Denis!