PDA

View Full Version : Rotation Controller


furystylee
12-27-2008, 02:46 PM
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?

JHN
12-27-2008, 04:03 PM
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\n"
/*
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

furystylee
12-27-2008, 04:34 PM
Many thanks for the help, Johan! I will try to absorb all this now and let you know how it goes. :applause:

furystylee
12-27-2008, 06:47 PM
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]

JHN
12-28-2008, 02:10 PM
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 4x3), 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

furystylee
12-29-2008, 02:16 AM
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:

JHN
12-29-2008, 11:40 AM
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

furystylee
12-30-2008, 05:58 AM
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

JHN
12-30-2008, 10:24 AM
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

furystylee
12-30-2008, 09:21 PM
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.
:beer:

thorn3d
12-30-2008, 09:36 PM
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

JHN
12-31-2008, 01:12 PM
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.
:beer:

Alright seems like I made a wrong claim about the controller input values, the output you get from x_rotation are in degrees, but the input from the rotation script is expected in radians (180/pi (roughly) = 57.2958 degrees) so what this means is that you need to convert the incoming degrees to radians, luckily maxscript has a build in function for this:

degToRad tracker.rotation.z_rotation

Why it exactly needs radians and not degrees I don't know, maybe someone else can answer that, build it probably has something to do with how the transform matrix expects it's input.

Cheers,
-Johan

furystylee
01-01-2009, 02:03 AM
You've found the magic formula!! Works perfectly! :D

Many many thanks

CGTalk Moderation
01-01-2009, 02:03 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.