the problem was in side of rotation – rotate to the left or right? cause dot product gives only angle. So we need to add check with help of cross product – result will always point in direction according to right hand rule. So if crossprod of rotated axis and its projection = axis of rotation it means that we should rotate clockwise – so quat should be inverted… and vise versa.
tm1 = $Box001.transform
tm2 = $Plane001.transform
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row1
axis3 = cross (normalize tm1.row2) (normalize tm2.row3)
rot = acos (dot rotdAxis (normalize axis3))
if rot>90 then rot-=180
rQuat = quat (rotAxis.x * (sin(rot / 2))) (rotAxis.y * (sin(rot / 2))) (rotAxis.z * (sin(rot / 2))) (cos (rot / 2))
if (normalize(cross rotdAxis axis3)) == rotAxis then rQuat = inverse rQuat else rQuat
rotate $Box001 rQuat
Hope this will work in all cases=)
If I’m reading this right, the way it’s supposed to work is:
-rotAxis is the axis it is rotating around
-rotdAxis is the axis that is supposed to get aligned to the target plane,
-axis3 is the cross of the rotAxis and the target plane.
Let me know if I’m misinterpreting that. If I’m not, then it still isn’t working all the time. Trying all the permutations in my test scene, this is what’s happening:
-- This works
rotAxis = normalize tm1.row1
rotdAxis = normalize tm1.row2
axis3 = cross (rotAxis) (normalize tm2.row1)
-- This doesn't
rotAxis = normalize tm1.row1
rotdAxis = normalize tm1.row2
axis3 = cross (rotAxis) (normalize tm2.row2)
-- This works
rotAxis = normalize tm1.row1
rotdAxis = normalize tm1.row2
axis3 = cross (rotAxis) (normalize tm2.row3)
-- This doesn't
rotAxis = normalize tm1.row1
rotdAxis = normalize tm1.row3
axis3 = cross (rotAxis) (normalize tm2.row1)
-- This doesn't
rotAxis = normalize tm1.row1
rotDAxis = normalize tm1.row3
axis3 = cross (rotAxis) (normalize tm2.row2)
-- This works
rotAxis = normalize tm1.row1
rotdAxis = normalize tm1.row3
axis3 = cross (rotAxis) (normalize tm2.row3)
-- This works
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row1
axis3 = cross (rotAxis) (normalize tm2.row1)
-- This doesn't
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row1
axis3 = cross (rotAxis) (normalize tm2.row2)
-- This doesn't (but works if used a second time)
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row1
axis3 = cross (rotAxis) (normalize tm2.row3)
-- This doesn't
rotAxis = normalize tml1.row2
rotdAxis = normalize tm1.row3
axis3 = cross (rotAxis) (normalize tm2.row1)
-- This doesn't
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row3
axis3 = cross (rotAxis) (normalize tm2.row2)
-- This works
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row3
axis3 = cross (rotAxis) (normalize tm2.row3)
-- This doesn't
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row1
axis3 = cross (rotAxis) (normalize tm2.row1)
-- This doesn't
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row1
axis3 = cross (rotAxis) (normalize tm2.row2)
-- This doesn't
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row1
axis3 = cross (rotAxis) (normalize tm2.row3)
-- This doesn't
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row2
axis3 = cross (rotAxis) (normalize tm2.row1)
-- This works
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row2
axis3 = cross (rotAxis) (normalize tm2.row2)
-- This works
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row2
axis3 = cross (rotAxis) (normalize tm2.row3)
its interesting) could you please share your scene where it doesn’t work, and what rotations you’re after and i’ll try it.
here is 105th version))
tm1 = $Box001.transform
tm2 = $Plane001.transform
rotAxis = normalize tm1.row2
rotdAxis = normalize tm1.row1
axis3 = cross (normalize tm1.row2) (normalize tm2.row3)
rot = acos (dot rotdAxis (normalize axis3))
if rot>90 then abs (rot-=180)
rQuat = quat (rotAxis.x * (sin(rot / 2))) (rotAxis.y * (sin(rot / 2))) (rotAxis.z * (sin(rot / 2))) (cos (rot / 2))
if (normalize(cross rotdAxis axis3)) == rotAxis then rquat = rquat else rquat = inverse rquat
rotate $Box001 rQuat
I think that actually made it worse… sorry
I don’t really have a specific scene I am testing this with, just making a box and a plane, and tilting the box off at random angles on x, y, and z…
so they are equal but last line return false. Even comparing them as strings returns true.
Hm, don’t know if this will help solve it or not, but I think with that last one, it might sometimes be rotating the right amount but in the wrong direction.
i know – the main problem is to find which direction to choose)
one more problem is rounding in 3ds max – sometimes it differs in 0.00001 and my test fails)
so i added some range… I don’t like this approach. want to find more convenient way of checking side of rotation.
tm1 = $Box001.transform
tm2 = $Plane001.transform
rotAxis = normalize tm1.row3
rotdAxis = normalize tm1.row2
axis3 = cross (normalize rotAxis) (normalize tm2.row3)
rot = acos (dot rotdAxis (normalize axis3))
if rot>90.0 then abs (rot-=180)
rQuat = quat (rotAxis.x * (sin(rot / 2))) (rotAxis.y * (sin(rot / 2))) (rotAxis.z * (sin(rot / 2))) (cos (rot / 2))
test = dot (normalize(cross rotdAxis axis3)) rotAxis
if (test >0.9999) and (test<1.0001) then rQuat = rQuat else rQuat = inverse rquat
rotate $Box001 rQuat
You are way better tester than me, so just ruin another attempt=)
That works for every single combination I tried! Thank you so much. I know it took a while longer to figure out than you expected it to, and I’m glad you stuck in there till you got it working
Incidentally, instead of using:
if (test >0.9999) and (test<1.0001) then rQuat = rQuat else rQuat = inverse rquat
This seems a bit more succinct:
if abs(test - 1) > .0001 then rQuat = inverse rquat
And yes, rounding in Max can be a real pain. I’ve had to add tolerances to scripts on more than one occasion when they shouldn’t have been necessary.