View Full Version : .dir for x and y axis ??
Gravey 02-04-2008, 11:40 PM I was wondering if there was an easy way to rotate objects when you know you want the x or y to be a certain vector like the way the .dir property works for the z axis.
If not what would the best method(s) ?
|
|
I was wondering if there was an easy way to rotate objects when you know you want the x or y to be a certain vector like the way the .dir property works for the z axis.
If not what would the best method(s) ?
someObject.transform -->gives you the transformation matrix
someObject.transform.row1 --> gives you the +X axis
someObject.transform.row2 --> gives you the +Y axis
someObject.transform.row3 --> gives you the +Z axis, same as .dir
someObject.transform.row4 --> gives you the position, same as .pos
You can also use indexed access, e.g. someObject.transform[1]
You might want to normalize() these, because if the Object Scale is not 100%, the vectors might not have length of 1.0
normalize someObject.transform.row1 --> normalized X axis
Once you know these, you would have to figure out the rotation.
You cannot simply set one of them like with .dir because the rest of the axes would not stay orthogonal. You will have to construct your own transformation matrix out of the desired X axis and the existing X axis. The normalized cross product of the two will give you a vector perpendicular to the plane of rotation. Then the normalized product of this new vector and the new X vector will give you the third component. The .row4 will remain the same. Assign the resulting Matrix3 value to the .transform property and your object will rotate as desired.
Here is an example:
*Create a Teapot
*Create a Point helper
Now to orient the X axis of the Teapot so that it looks at the Point Helper, you can say
(
oldTM = $Teapot01.transform --this is the original matrix
oldX = oldTM.row1 --this is the original X axis
newX = normalize ($Point01.pos-$Teapot01.pos) --this is the new X axis
newY = normalize (cross newX oldX ) --this is the new Y axis based on old and new X
newZ = normalize (cross newX newY ) --this is the new Z axis based on new X and Y
$Teapot01.transform = matrix3 newX newY newZ oldTM.row4 --this is the new transform
)
You should not call this if old and new X axes are identical, because the resulting Y would be incorrect (cross product of parallel vectors!). It might be worth it checking that they are indeed different before performing the rest of the operations.
Gravey
02-05-2008, 03:52 AM
Thanks Bobo for the info and example.
I've use the constructing matricies method before but what happens if there was some non uniform scaling on arbitrary axis that you want to retain? I've just discovered that the .dir doesn't do this anyway so out with that idea...
Thanks Bobo for the info and example.
I've use the constructing matricies method before but what happens if there was some non uniform scaling on arbitrary axis that you want to retain? I've just discovered that the .dir doesn't do this anyway so out with that idea...
You could retain those - the NU (or any) scaling is encoded in the X, Y and Z components (the first 3 rows) as the length of these vectors. So it would be rather easy to multiply each normalized vector by the corresponding scale component.
That being said, NO OBJECT IN MAX should ever have Scale at Object Level or bad things could happen along the way. Just a matter of principle ;)
Gravey
02-05-2008, 06:28 AM
You could retain those - the NU (or any) scaling is encoded in the X, Y and Z components (the first 3 rows) as the length of these vectors. So it would be rather easy to multiply each normalized vector by the corresponding scale component.
Sorry I wasn't quite clear. I'll give you an example:
make a point helper
make a teapot and rotate it at some random angle
scale the teapot in world space along the x y and z axis individually by different amounts. The bounding box will appear skewed
now run this modified version of the code you supplied me earlier which now accounts for scale:(
oldTM = $Teapot01.transform
oldX = oldTM.row1
newX = (normalize ($Point01.pos-$Teapot01.pos)) * (length oldTM.row1)
newY = (normalize (cross newX oldX )) * (length oldTM.row2)
newZ = (normalize (cross newX newY )) * (length oldTM.row3)
$Teapot01.transform = matrix3 newX newY newZ oldTM.row4
) the scale is still there but the bounding box is no longer skewed
That being said, NO OBJECT IN MAX should ever have Scale at Object Level or bad things could happen along the way. Just a matter of principle ;) I'm aware of this however I'm trying to account for any object that a user may want to use, even if the scale is so messed up that it makes you want to cry! ;)
I guess I could just leave instructions for the user to resetXForm the objects first... but again, they may want it like that for some unknown reason.
Scaling a rotated object in world space scales the LOCAL axes differently and can cause them to stop being orthogonal to each other. (A Really Really Bad Thing in computer graphics - I hope you are not serious about using an object scaled this way)
My rotation method relies on the fact that a GOOD and HEALTHY transformation matrix IS orthogonal. Of course, the code would reorthogonalize the transformations and get rid of the skewing.
A workaround would be to calculate a rotation matrix that brings the X axis where you want it by transforming the existing matrix instead of building a new orthogonal one.
Gravey
02-05-2008, 09:42 AM
Thanks again for the info. I hope that I never have to deal with unorthagonal matricies and i personally never scale objects unless i intend to resetXForm straight away, but I thought it would be a good exercise none the less. Cheers
CGTalk Moderation
02-05-2008, 09:42 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.
vBulletin v3.0.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.