View Full Version : retrieving rotation values > 360
09-10-2009, 01:45 PM
I'm developing a utility in max script, part of which fundamentally requirres the total local (X,Y or Z) rotation of an object. In the curve editor, you can plainly see a value ranging from 0 to lets say 1080 for an object rotating through several revolutions.
I've tried several methods to get this data back out, the best I've come up with is very convoluted, and history dependant (which is a massive deal breaker for long animations) method. This is due, possibly to my lack of understanding of the transform matrix, or possibly due to the limitations of quats, and euler angles.
I have a CA (absPos), float script, which very successfully calculates the Absolute angle of the requirred axis using a couple conditions based on the following (where source is Node, child of the object being measured) :
((in coordsys gimbal quattoeuler source.parent.transform.rotationpart).z_rotation)
it then converts the Euler +/- 180 to 0 -360, then re-scales the values based on a user specified optional modulous ultimately giving a distance travellled.
Another CA, looks at the above absPos, calculates the difference in the value in time F vs time F-1 to give a speed.
The problem I run into is that in addition to the above, I need to track the total rotational distance travelled over the course of the animation, and display it to the user as a CA.
No matter where i looked i could not find a place max stores values similar to the ones you'd see in the curve editor for a multi-rotational object.
The best i could come up with was to take my initial rotation value, then increment it based on displacement derrived from the speed CA above.
I found i could not reliably do this without a for loop ranging from time 0 to the currentframe. (as the CA gets recalulated for lots of reasons, not just for timeline changes) This makes it history dependant, and very slow (every time opening the curve editor was a nightmare)
So i moved the little for loop into an already existing function running as a timecallback. this way, if the time incremented forward or back exactly one frame, all i had to do was add or subtract the displacement, and only run the for-loop if the user jumped a number of frames ahead. Unfortunately with longer animations, this seems to happen all the time, which means the animation ends up running worse then 1fps at times.
Long story short, I feel broken. Any advice?
09-29-2009, 04:25 AM
Further to this I bought Bobo's great Advanced Maxscript DVD... Quite a few good nuggets in there. Chapter 4 contains a scene where there is an angle displayed for a vector which rotates through > 360 degrees. Does anyone have the scene source file, as it is one that did not come on the DVD?
Or, better yet.... Hey Bobo, any chance you can tell me how you did that? I might provide a clue to my delema...
09-29-2009, 09:24 AM
getting the value explicitly from the rotation controller will do what you need:-- gets the x rotation value at the current time
-- gets the x rotation value at frame 20
at time 20f $.rotation.controller.value
10-05-2009, 12:48 AM
You're my new hero!
Thanks very much. That Solves a lot of grief I was having. I assume this won't work if the object's rotation is coming from a different type of controller? (i.e. the bank of a path constraint) I'll still have to jump through hoops for that sort of stuff I'm guessing?
PM me if you happen to freelance :)
10-05-2009, 12:36 PM
you can use the expose transform helper to extract local and world space positions and rotations from objects that are controlled by constraints (like the path constraint) but i'm not sure if the values will be accessible > 360.
sent you a PM
10-05-2009, 08:23 PM
yah, yea olde expose tms only seem to play <360...
10-05-2009, 09:57 PM
I am digging into the rotation values as well. It is quite painful (at least for me it is)
you can grab the value of a object's rotation as stated above so long as you remember that it is going to come back to you as a Quaterion Rotation matrix. Which seems to be how Max is storing all of its rotations.
Euler Rotations that are displayed of course only show +/- 180 for their values. But are then converted into Quaterions behind the scene. You can use angleAxis to achieve a rotation of greater than 360 degrees.
When I have been scripting the rotations for objects that are parented I have been doing the following
set coordsys world
To change the objects rotation I use
in coordsys local $.rotation = eulerAngle # # #
# equals the degree of rotation in X Y Z
To reset to a zero rotation I can then use
in coordsys gimbal $.rotation = eulerAngle 0 0 0
This reset the rotation of the selected object back to its Zero rotation that is being preserved by the world coordinate system.
I am really unimpressed by Max's ability to maintain and set rotation values.
Thinking about your specific problem though. What you might do the rotation value in local space everytime it happens and feed that rotation value into an array. Then display the sum of the array in a message or rollout.
basically every key frame rotation would push a number appended to the end of an array. Then do a loop based on how the .count in the array.
10-05-2009, 10:29 PM
Yah, i feel your pain. All it would take is an expose TM that tracked multiple revolutions, and that would jive with how things work in general. quats rock otherwise.
I have script controllers generating speed and acceleration curves for rotation, and i have to jump through all kind of hoops to check for direction of travel for the 0 to 180 or -180 to 0 swap etc. It's all working at the moment, but if frames get skipped it basically needs to do a history dependent solve, and boy does that suck when you're on frame one billion. :p
10-05-2009, 10:45 PM
I am just used to Maya where I have all the rotations exposed in a standardized format (ie all the values match so that if I type in 720 degrees that what shows in all of exposed values. Graph, dope, and channel box) This assine use of one value matrix and swapped for another is just annoying and reaks of poorly written app. I am having to deal with it at the moment. But I am finding that it is not a well written app in a number of ways. It's mostly simple things that I have been able to do in other apps (not just maya) for over a Decade. Argh!
Max may be a good modeling app, but it is almost more lacking in someways than Lightwave in the animation dept.
10-05-2009, 10:54 PM
We had the option of going with Maya before we went down this road, and sadly, the bank ballances and skills of most of our clients decided on 3ds max... Sigh. In max's defence though, I have to say that rotation is the only place I've really been hung up and resorted to putting stuff into maxscript when it would have been much more eligant in a script controller on a CA. The learning curve for max/maxscript/sdk hasn't been too bad in general.
10-05-2009, 11:33 PM
well in the future it will be good to know that Autodesk as of max and maya 2010 has normalized the price point and subscruption cost. Maya complete was cheaper but they raised the price and included all the fetures of unlimited with it,, and lowered the subscription fee for renewal. As of the annoucement a license holder for Maya or Max can change their license between applications once per renew cycle. At least that is the way it was brought across.
10-05-2009, 11:53 PM
Awesome!! Did not know that.
Part of the problem with Max and rotations comes from the list controllers. Because Max can have unlimited number of nested layers of animation on any given track it is hard to track it all. That being said it is also way better then Maya for this reason as any track of animation can have this sort of layering of animation since Max 1. The one big thing that I really miss when working in Maya are list controllers.
10-06-2009, 12:18 AM
The assertion that maya's rotation representation is better than max's one sounds pretty strange and unfounded for me. Maya uses only Euler type of rotation controller and there is no any difference between "max" or "maya" Euler angles. Any transform calculation based (for both max and maya) on quaternions. And quaternions are used for rotation interpolation.
There is no way to get the number of revolutions around an abstract axis at abstract time. And it doesn't make any sense. There are 9 (maybe i'm wrong but i'm too lazy to count) different Euler angles combinations to represent the same rotation. So, to get the number of revolutions you have to know at least initial node's rotation and way how this node came to current state.
If your are using Euler controller in max (same as maya) it is not a problem to get a value for any axis over 360 degrees. Right?
If you a using your own scripted controller it's better to make a property to count the number of revolutions or to handle a rotation angle about some axis (aka spin).
If you want to know how many times some object spinned around on time interval, and the only thing that you know about this node is its transform matrix at any time -
you have to get this value for every tick (frame, millisecond, whatever...) using animation range.
10-06-2009, 02:56 AM
Maya does not use just Euler type rotations. You can set to use Euler or Quaterion Rotations. And regardless it still only has one listed rotation.
The individual problem that I am wrestling against is that Max has a problem with reset back to a world zero rotation once an object has been frozen. It appears to lose all that rotation information. Max writes the value as a Quaterion Rotation Matrix. Now I am still new to Max and MaxScripting. So I am willing to bet there is someplace this value is stored somewhere in Max that I have not unearthed just yet.
However what I have have learned from the Max Docs is that Max's Euler Rotation only works within the bounds of +/- 180 so it has to be keyed every 179.9 degrees otherwise there is no rotation.
@ Pen you can add any number of additional controls to any object in Maya. It just a matter of what you want it to do specifically. Also I do quite admire the tools you wrote.
10-06-2009, 12:28 PM
This rotation > 360 issue just matters, if you blend keys. To prevent this, just check each previous key of the controller if it is in reach of 360, if not, just - / + 180.
I made some time ago a function to extract all keyed controllers from nodes which are keyed.
It just recursivly goes through all controllers and checks the keys and returns the controller with their properties, without caring about the type of controller or property.
At the end, you just go through the key array and do this check :)
Btw. you can access the properties of each key (MAXKey) with GetProperty <key> <propertyName>
and you can get all of the available properties by using GetPropNames on the key itself.
With SetProperty you can instantly change the keys values (works quite well for tangent stuff too).
This way it is much faster to update rotations for an animation, as the system does not need to update by time at all, you basically overwrite stuff directly on the key.
10-06-2009, 12:28 PM
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.