rotation script controller Help

This information will be useful in the future: I started scripting 4 weeks ago

So here´s my problem... Im using a rotation script controller replacing the Euler XYZ for a DummyA in order to make it rotate reacting to the difference between two other dummies (B and C)
I use something like this in the scriptcontroller:

dependsOn $DummyB $DummyC
$DummyB.rotation - $DummyC.rotation

and it works like a champ... but when i try to apply some math to that value it doesn´t seem to be working at all, like

($DummyB.rotation - $DummyC.rotation) * 0.5

which i tried in order to make it rotate half of that value
My problem is that I need to use that rotation and paste it to other Dummies so they rotate half the speed and less like "* 0.8" or "* 0.2"
If I do this with wire parameters it works perfectly even if i rotate the master (DummyC) more than 180 degrees. This was not possible with orientation constraints.
My problem is that I can´t use wire parameters since this dummies are inside and parented to different objects in the scene and i´m trying to avoind solving it with one extra slider in my rig.

What am I doing wrong?
I found the slerp function for quaternions but when i try to use it inside of my controller it doesn´t seem to work
Please Help


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
MKlejnowski's picture

The reason ($DummyB.rotation

The reason ($DummyB.rotation - $DummyC.rotation) * 0.5 does not work properly is because the script controller uses quat values as opposed to the euler angles. Quaternion math a bit harder to grasp and sadly not so simple.

So you said wiring them seems to work for you. Why go with the script controller then? Why do you need another controller with wiring? I'm having trouble understanding what your having an issue with.

lexloopor's picture

ill try to explain better

First of all thanks a lot for answering!
This is what Ive done untill now and what I need... it will be probably easier to understand:
I have objectA and objectB (yellow dots in attached file)
both are looking at eachother (look at constraint) but have position constraints with different objects. (this is something that i do to get only the x rotation when i calculate the difference between A and B)
Both have different upnodes in the orientation constraint
I have three test objects (red points in the attached files)
and i want them to rotate 25 50 and 75 percent of that rotation difference
i also want them to rotate averaging even when the objectB rotates more than 360 degrees

the max has some animation... of course this is a simplified version of what i want to do but it has the same issue and you can see why i cant use a wire

hope it helps

what i found until now is something like this (script controller over the transform of my test points)

dependson $objectA $objectB
r1 = $objectA.transform.rotationpart
r2 = $objectB.transform.rotationpart
r = slerp (normalize r1) (normalize r2) 0.5
--(or 0.25 or 0.75)

t = $TestObjectParent.transform.translationpart
--($TestObjectParent is the object which i will use to control the position of the test objects)

s = $TestObjectParent.transform.scalepart

Is this correct? if so... how do i put the matrix back together with all this values... will this work when the rotation goes above 360 degrees?

Thanks for reading!

v4.max 220 KB
MKlejnowski's picture

(r as matrix3) * (scaleMatrix

(r as matrix3) * (scaleMatrix s) * (transMatrix t)
this would make a new transform matrix for the rotation position and scale but it would not rotate the way you want it.

Slerp uses the shortest distance to achieve the rotation. This might help you understand it a little better of why it wouldn't work.

eulerToQuat (eulerAngles -90 0 0) --result will be (quat 0.707107 0 0 0.707107)
eulerToQuat (eulerAngles 270 0 0) --result will be (quat 0.707107 0 0 0.707107)
(eulerAngles -90 0 0) == (eulerAngles 270 0 0) --this will equal false
eulerToQuat (eulerAngles -90 0 0) == eulerToQuat (eulerAngles 270 0 0) -- this will equal true
quatToEuler (quat 0.707107 0 0 0.707107) -- will always be (eulerAngles -90 0 0)

The rotation property of a node or in other words $.rotation return a quat value. A 50% from (eulerAngles 0 0 0) to (eulerAngles 270 0 0) would be (eulerAngles 135 0 0). Slerp calculates Quat values and not Euler so it would treat(eulerAngles 270 0 0) as (eulerAngles -90 0 0) thus making the 50% a (eulerAngles -45 0 0).

lexloopor's picture

so what should i do?

I am starting to understand how quat values work (just a bit) but then what should I do? if i can´t wire or use orientation constraints and I want to have the same result as when i use wire on objects with the same parent.
Is there any way to extract that rotation as if the parent is the same of the test objects parent?
Again thanks for taking the time to answer

barigazy's picture

To get node’s rotation

To get node’s rotation relatively to its parent u can use

$.rotInParent  --you will recive point3 value as result


lexloopor's picture


can I get the rotation relatively to another object which is not the parent?

barigazy's picture


Are you try

-- let say you have two objects stored in variables "curObj" and "otherObj"
rot = in coordsys otherObj curObj.rotation

Or you can use ExposeTm helper object, align to other object and pick curObject.
You can see then all infos that you need


lexloopor's picture


I didn´t know about the ExposeTm helper... super tool! I just tried using it but if y try to wire it and apply a *0.5 it will jump as expected when i pass the 180 degrees... what a shame!
When I tried using $.rotInParent i got values even when i rotated over 360 degrees...
Basically if I find a way to get values over 360 degrees in the same way (respectively to another object which is not the parent) as using ExposeTm helper I would be able to finish my rig
besides all that... I really apreciate your help, hope I can help with something some day

MKlejnowski's picture

If you want to have rotations

If you want to have rotations not flip while when it goes over 180 then your gonna have to depend on the Euler Values from the Euler rotation controller from your reference node.

Here is a copy of your current file with a float script on the x rotation controller with in the Rotation controller. If this is what your looking for or if it works as expected let me know.

Im using Max 2011 so i hope you can open it.

v4.max 228 KB
lexloopor's picture

yes and no

it is what i was looking for in terms of how the values work but I´m still taking the value from the absolute x euler of the control... since the control is not parented and free from the rest of the system y created the extra point ($objectB which you hided) but that point has an orientation constraint on it so i don´t have that track to select... that´s why in the beginning I tried to extract that value getting the difference between two point.
As you can see in this file when you move the control spline around even if you rotate it to look at the system the other bones will stop working which makes sense because the euler of the value that You´re taking is a world value and it´s not referenced to the system coordsystem.
Now Im starting to think that the difference between those two rotations will never give me a value over 360...
The system is a very complex rig of a tentacle arm with stretchy bones and controls for every joint... right now I´m using the control for the position of the IK and the extra control for the rotation. I´t can´t be impossible to keep the last bone of that rig aligned to the control and the rest averaging to that rotation
If i ask for $.rotInParent i get a value in degrees and if i rotate $ over 360 I get that value like 854 degrees. Now if I ask for the rotation like barigazy said:
"rot = in coordsys otherObj curObj.rotation"
I´m getting different values (quat i think)... any ideas?
I´m learning more in this conversations than what I´ve learned in weeks Thanks again.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.