[Closed] Rotation Controller
I’m trying to create a rotation controller – rotation script that matches another object. So on every frame the sphere will match the box’s rotation.
So in the listener i type this:
boxXrot = $box01.rotation.x_rotation
boxYrot = $box01.rotation.y_rotation
boxZrot = $box01.rotation.z_rotation
and in the sphere’s rotation controller script i type this:
[boxXrot,boxYrot,boxZrot]
But I get this error:
MAXScript Script Controller Exception: – Unable to convert: [2.73677,-22.7071,-36.6834] to type: Quaternion <<
What do I need to do get the rotation to match using this method?
Well, lots ot things are going wrong here Let’s have a look.
There’s a lot of way’s to go about this, you could copy the rotation controller from one object the another
selection[1].rotation.controller = selection[2].rotation.controller
Then there’s also the rotation constraint. Which speaks for itself.
But your saying you want a script controller (if you simply want the same rotation I suggest the first approach!).
All rotations eventually need a quaternion value as input (even XYZ controllers). I assume you have assigned a script controller to an object and typed in “[boxXrot,boxYrot,boxZrot]”. Which is going to be a problem since rotation requires a quad value not a point3. Also you are using the script controller the wrong way. Assigning a value to a variable (for example boxXrot) in the listener doesn’t ensure max knows for all time to come the script controller even knows what “boxXrot” means… a simple restart of max will wipe that variable. You need to tell the script controller which object to track.
So in the script controller you type in trackObj in the variable field and click on assign node and pick the other node. Then in the script window type in “inverse trackObj.rotation”. Now you have assigned the node you want the rotation off to the script controller and told it to get it’s rotation on evaluation time.
A script sample
(
-- Set the objects to work with
obj1 = box()
obj2 = box()
-- Create a script rotation controller
sc = rotation_script()
-- Assign it
obj1.rotation.controller = sc
-- Add the second object to track it's rotation
sc.addNode "tracker" obj2
-- Add the simple script
sc.SetExpression "inverse tracker.rotation
"
/*
the rotation needs to be multiplied with the inverse of it's parent object (look that up!)
since world is the parent it's enough to just inverse the rotation value
*/
)
-Johan
Many thanks for the help, Johan! I will try to absorb all this now and let you know how it goes. :applause:
aha! ok I’m able to get it rotating along with my controller object! I will definitely need to study more about max rotations
i have more questions about controllers (of course!). Let’s say in this case I wanted to follow only the x translation. So in obj1’s Position – X Position, I create a float script and create a variable called “trackerX” and choose obj2 as the node.
Now how do I refer to only the x translation in the expression? or is that assumed because its an X position controller?
$Root.pos = [trackerX,0,0]
if you create a script controller only on X and assign the “tracker” node to the script controller node option then the expression would be
tracker.position.x
No need to inverse anything here. And yes it’s assumed that only a single floating point is returned by the expression, that why assigning a script controller to only the X controller of the position is called a float_script it should return a single float, assigning a script controller to the position controller is called position_script and the controller should return a point3 value, as you see all controller are different although they apply the same principles. You could even assign a script controller to the transform controller of an object (transform_script) then the script should be returning transform values (matrix 4×3), that is position rotation and scale in 1 go.
You should do good reading up on matrices, rotations (quads) and controllers, there’s lot’s of very good info in the mxs help file.
Goodluck,
-Johan
super helpful, thank you. :bowdown:
I ran into an issue when applying an expression to a z rotation controller:
I’m trying to match z rot of objA to objB, but objA is the child of objB (inheritance flags have been removed). Whats happening is the expression tracker.rotation.z is only giving me about half the rotation value i need. It works fine when the obj is not the child.
I’ve attached an example. lol i think this is the last hurdle in my script :drool:
Please read up on quat values… .z gives one of the four values a quat is build up of, try “tracker.rotation.x_rotation” will return a euler X value.
-Johan
ok it seems that a float_script expression on a z rotation axis is looking for only a single quaternion value. even when I manage to get the correct quat .z value in it isn’t acting correctly. isn’t the point of quat is that it needs all 4 values to work?
only when i do a rotation_script and enter the full quat value do i get it to work properly. its when i try to single out an axis im getting into trouble
It’s not expecting a single quat value, it’s expecting a single euler value in the form of a degree 0-360. Eulerangles can be retrieved from quats by <quatValue>.x_rotation etc.
At the end of evaluating the euler controller there is a quat value left but the individual X, Y and Z are expecting. I don’t know why you’re not getting the values you’re expecting, but when you rotate a parent object you change the way a child object rotates as well, since you’re transforming the object’s parent space, from which the transforms take place. Maybe if you post an example I could have a look what’s going on.
Goodluck,
-Johan
I’ve attached a test file. Box02 has a float script on z rotation that is tracking the animated Box01’s. If you can check it out that would be excellent.
It’s been awhile since I’ve done this (so correct me if i’m wrong). If you aren’t getting full rotations due to parent/child relationships, it’s because you aren’t converting/evaluating the rotations in world space – which you need to do within your script.
thorn