local rotation - manipulation tool

i am working on a modeling app with a rotation manipulation tool.

i am trying to get the manipulation tool to rotate in the transformed object space.


that is an example of selecting the transformed x axis of the object, but in most cases i cannot get the actual rotation to happen on the selected axis only while retaining the rotation of the non selected axes. ( rotate the object in place on the orientation of the selected axis )

i can use a custom matrix, quaternions, whatever, i just cannot seem to figure out the right one or combination of them. i can easily get it to work on one axis at a time, but then the other two do not work properly. i know it is because the axes are getting transformed themselves, i guess i cannot figure out how to transform the appropriate values for them.

any help or pointers would be greatly appreciated. i would like to keep a consistent rotation transform that consists of three angles for each axis. but, when a certain axis is selected i would like to rotate around that axis only in object space and have the 3 transform angles update appropriately.

something similar to what maya does. it appears that they do their rotation transform with something like…

glRotated( angle, 0.0, 0.0, 1.0 );
glRotated( angle, 0.0, 1.0, 0.0 );
glRotated( angle, 1.0, 0.0, 0.0 );

… or something similar using a matrix that is most likely the combination of these.

when u rotate on x only the x value of the rotation transform changes, because it is the last matrix multiplied. but when u rotate on y or z, the rotation happens on the local axis only, but in many cases all three angles of the transform change.

this is exactly what i am trying to accomplish. however, i cannot calculate the values of these angles properly.


Hi Gandalf,

If you have circular dependencies in your rotation order then you’re probably in a pickle.

I’m not exactly sure what your problem is (I don’t use Maya).

Are you after angles, or just a basis of some kind?

i am after angles.

i know i can accomplish what i want by directly changing vertex values, rotating around a certain single axis as i need to no matter orientation. being able to do that one at a time is trivial, but doing it while maintaining three angle values as part of a transform i am finding impossible.

ultimately i want to maintain a rotation transform for all three values around a local axis for the object that changes with each rotation when the maniptool is used. when the object is being rotated about x , the y and z axes will change but x remains fixed from where it was selected and rotation only occurs about x in object space. so the transform needs to update with the new appropriate y and z angle values for the new orientation of those axes, including the new rotation value for x. i know it is possible, just not sure how.

the reason for all of this being that at any time u can simply reverse the angles of the transform to get the object back in line with the world axes.

hope that description helps. thanks for the response.

Hmmm, I think it’s clear now. It always helps to get back to the math that’s going on; look at the matrices.

For the sake of argument, let’s suppose the user has performed the following rotations on the selected axes.

M = Rx Ry Rz Rx Ry Rx Rz Ry Rx.

It’s clear that

M != Rx Ry Rz,

or any other permutation of that order. Therefore, a simple, 3 rotation arrangement is not going to cut the mustard.

However, it is true that

M = Rx’ Ry’ Rz’,

where the Rs are derived from the final matrix, M. Since these are just rotations around the principal axes, we could use a conversion to take our final matrix, M, to Euler angles.

You might want to look at quaternions to keep track of the orientation, then simply convert the orientation to Euler angles whenever you see fit. Quaternions are very nice in this situation, since a normalized quaternion always represents a rotation. We thus avoid the axial drift associated with Eulers, not to mention the trouble with our gimbals.

With quaternions, the matrix example above would look like this:

Q = Qx Qy Qz Qx Qy Qx Qz Qy Qx,

where each Qi is an axis-angle quaternion. We can then derive our Euler angles from the current quaternion, Q. Note that it’s a good idea to normalize Q after each update: there’s numerical drift, but if we normalize we’re sure to have a rotation.

Google has the goods on quaternions and Euler angle conversions. Try a search for “trackball,” too (you might find it interesting).

I hope this helps. And if I missed the mark completely, thank the Old Winyard :wink:

[edit: clarification]

thanks graham.

i know how to do a trackball, that does not really help me in this situation as i want to rotate around one of the three local axes, and i know how to use quaternions and how to convert them to a matrix and euler angles which does certainly help.

however, my main problem is maintaining some sort of x,y,z angle transform while being able to rotate on each independently in local object space. a transform that as such, if i applied the inverse of all three rotations the object would be aligned with the world x,y,z axes.

so let’s say i have a cube with a transform 45:x,30:y,60:z respectively and i want to rotate around the local z axis. now i can deterimine a single axis to apply this rotation no problem based on the object’s orientation, say another 35 degrees on z so now we have 45,30,95. so then the big question is ( what i cannot figure out ), is how to apply that transform on an object with a 0,0,0 transform and have it end up at the same spot as the object with th 45,30,95 rotation transform?? how do i adjust for the changing axes and represent these in the transform?? i would assume that the transform must always reflect as if it is rotated about a fixed axis. or maybe i can keep new axis orientation info somewhere else which is fine. maya sometimes changes the value of all three angles of the transform when applying a single local rotation, so their transform is obviously represented on a fixed axis like i stated in my first post. i can do that, or constantly change the 3 axis values, i do not really care, i just want to be able to keep track of the transform so i can easily put it back to where it was. i just cannot figure out how to properly calculate the angles or axes.


actually after reading your last post more closely this time u certainly understand the question. i need to derive Rx’ Ry’ Rz’ from M, which makes complete sense. i should be able to figure that out from somewhow, thanks again.

ok i think i have got it now, i will post back after i can test it and implement it later, the solution seems really simple now. i should just be able to use a single quaternion to do an axis,angle rotation and then convert that to euler angles that would represent the transform.

do not know why i could not think of that earlier.

That sounds good to me.

Just out of curiosity, is this a character editor, and do I get a free copy when it’s done? :slight_smile:

I’m working on my own editor for a little game engine I’m playing with. I might end up using something similar to this for manipulating actors/geometry. Seems like another tricky bit will be making the mouse movement feel natural and the rotations intuitive irrespective of orientation.

Anyway, it’s fun stuff.

well i do have something working finally.

i keep three unit vectors representing the axes and transform them accordingly with each new rotation before making the quaternion. i can then use a single quaternion to represent the rotation of an object. then i can simply multiply that existing quaternion representing the old orientation with a new one representing a new rotation from the manipulation tool around one of the selected transformed axes of the object, convert that to a matrix and i have my local transform. i can easily select each axis and do a true fixed axis local rotation around it.

i can then simply get the euler angles from the resulting matrix.

thanks for the help, and yes the idea will soon be to edit characters as well but i am afraid that will be a little ways off yet. maybe i’ll make another post when it is done.