View Full Version : Non twisting IK Arm/Leg problem

08-07-2006, 11:53 AM

I'm trying to create a non twisting IK arm/leg chain. I want an IK arm which only bends but doesn't twist - the mesh should not collapse because of twisting (like it is happening at the shoulder of an IK arm). This makes the rotations very complicated for me. I've done some R&D and came up with scripted controllers for upper arm and lower arm rotations (specifically for X rotations). I found their x rotations depending on the shoulder x,y,z rotations and their own y,z rotations. I found out how they depend on all those rotations except the shoulder y rotation. This really gives me some headache now. I searched the forum and Google for a possible solution, but didn't find anything dealing with it although I think this must have been solved somewhere already. Here is the code for the upper arm sripted rotation controller:

--get upper arm bone own rotations
A01y = A01.rotation.y_rotation
A01ys = A01y/abs(A01y)
A01z = A01.rotation.z_rotation

--get shoulder rotations
Shx = Sh.rotation.x_rotation
--Shy = Sh.rotation.y_rotation
--Shys = Shy/abs(Shy)
Shz = Sh.rotation.z_rotation

--difference of shoulder and upper arm bone z rotations
Rz = A01z-Shz

--"limit" the difference of z rotations to -180..180 degrees
REZ = ((eulerAngles 0 0 Rz) as quat) as eulerAngles
REzs = REZ.z/abs(REZ.z)

--main part of the upper arm x rotation
X = 180 * REzs * A01ys * (abs(REZ.z)/180)^(90/abs(A01y)/)

--build upper arm rotation
eulerAngles (X+Shx) A01y A01z

With this you can rotate the upper arm in any direction and the shoulder around x and z without the mesh collapsing. Unfortunately I don't know how the shoulder y rotation influences X in the script (formula). I believe it might well be possible that there is a much more elegant solution to that problem than my approach, but I don't know 3ds Max all that well. Many thank's for help.

08-08-2006, 11:20 AM
I think that you are way over complicating it. Have a look at the Expose Transform Helper as that is what you need. Or you can just get my DVD's and that will cover that and many more issues that you will run into.

08-09-2006, 09:52 AM
Hello again,

first I thank you, Paul, for pointing me to the ExposeTm helper, although it didn't solve my problem. However, with this it's a little less complicated to get the real local and world rotations of bones in an IK chain. Whereas I had to align and link an object to the IK bone in question (then use the rotations of that object) to get the actual rotations, I now can use the helper instead. I have to go through more of the tutorials and reference coming with 3ds Max so that I know more about wich tools are actually available.

Finally I found the solution for my problem. I already had the idea that I would need to compute the arm bone rotations in the coordinate system of the shoulder and then transform this back into world space, but I didn't know how to get into world space then. Yesterday I found out that this is rather easy. I needed to invert the Shoulder rotation matrix and rotate the bone rotation with that result. So the command "rotate()" is the actual solution to my problem. For others who might want to do an extremity without a collapsing mesh because of twisting I attatched the code for the scripted controllers of the "skin bones".

Scripted rotation controller for upper arm skin bone:

--A01: upper arm IK bone
A01y = A01.localEulerY
A01ys = A01y/abs(A01y)
A01z = A01.localEulerZ
A01zs = A01z/abs(A01z)

--Sh: shoulder bone
Si = inverse(Sh.rotation as matrix3)

--the actual rotation calculation
X = 180 * A01ys * A01zs * (abs(A01z)/180)^(90/abs(A01y))

A01M = (eulerAngles X A01y A01z) as matrix3

--transform back into world space
rotate A01M Si

Scripted rotation controller for lower arm skin bone:

A01Wx = A01.worldEulerX

A01x = A01.localEulerX
A01y = A01.localEulerY
Ays = A01y/abs(A01y)
A01z = A01.localEulerZ
Azs = A01z/abs(A01z)

--A02: lower arm IK bone
A02Wx = A02.worldEulerX
A02Wy = A02.worldEulerY
A02Wz = A02.worldEulerZ

Si = inverse (Sh.rotation as matrix3)

X = 180 * Ays * Azs * (abs(A01z)/180)^(90/abs(A01y))

RM = (eulerAngles X A01y A01z) as matrix3

R = (rotate RM Si) as eulerAngles

--the difference between upper and lower arm bone needs to be taken into account
eulerAngles (R.x + (A02Wx-A01Wx)) A02Wy A02Wz

This seems rather complicated, but it is the easiest way I could find. And after all: it's now working exactly the way I want - no twisting or collapsing whatsoever.

08-10-2006, 11:58 AM
This isn't the easiest way, your code is impressive but again I think that you have way over complicated it. You might want to get my DVD series on rigging in Max and that might help you with other issues that will arise as well. You can get to them from the link in my signature if you are interested.

The Expose TM helper is all that you need or another way is to do it with lookAt constraints and you can see that method on my site in the tutorials section. I would use the ExTm method now though.

CGTalk Moderation
08-10-2006, 11:58 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.