In case anyone ever wants a nice, easy to use function:
fn alignAxisToPlane obj tgt:undefined r:"y" a:"z" p:"xy" =
(
tm1 = obj.transform
if tgt == undefined then tm2 = (matrix3 1) else tm2 = tgt.transform
if r == "x" do rotAxis = tm1.row1
if r == "y" do rotAxis = tm1.row2
if r == "z" do rotAxis = tm1.row3
if a == "x" do alignAxis = tm1.row1
if a == "y" do alignAxis = tm1.row2
if a == "z" do alignAxis = tm1.row3
if p == "yz" do tgtPlane = tm2.row1
if p == "xz" do tgtPlane = tm2.row2
if p == "xy" do tgtPlane = tm2.row3
axis3 = cross (normalize rotAxis) (normalize tgtPlane)
rot = acos (dot alignAxis (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 alignAxis axis3)) rotAxis
if abs(test - 1) > .0001 then rQuat = inverse rquat
rotate obj rQuat
)
-- Sample usage:
alignAxisToPlane $ r:"z" a:"y"
i don’t want to disappoint you but the function is not correct.
it’s very easy to check… if you run your function second time with the same arguments the result shouldn’t change…
Yeah, I actually noticed that not long after I posted… Any suggestions for fixing it?
(oh, and 3ak: I’m not the one who broke it this time )
here is what i would do:
fn makeRotateMatrix vector angle =
(
x = vector.x
y = vector.y
z = vector.z
cs = angle
sn = sqrt (1 - cs*cs)
row1 = [cs + (1-cs)*x*x, (1-cs)*x*y - sn*z, (1-cs)*x*z + sn*y]
row2 = [(1-cs)*y*x + sn*z, cs + (1-cs)*y*y, (1-cs)*y*z - sn*x]
row3 = [(1-cs)*x*z - sn*y, (1-cs)*y*z + sn*x, cs + (1-cs)*z*z]
matrix3 row1 row2 row3 [0,0,0]
)
fn alignAxisToDir node axis:#z dir:[0,0,1] =
(
vec = case axis of
(
#x: node.transform[1]
#y: node.transform[2]
#z: node.transform[3]
)
tm = node.transform
vec = normalize vec
dir = normalize dir
rtm = makeRotateMatrix (normalize (cross dir vec)) (dot vec dir)
node.transform = translate (rotate (scalematrix tm.scale) (tm*rtm).rotation) tm.pos
)
/*
-- example:
alignAxisToDir <source> axis:#x dir:<target>.transform[3]
*/
if anyone know an easier way how to make the rotation matrix please share
You wrote that my func returns different results. i created box, plane, rotated them randomly, run my script. it aligned box to plane (let’s say rotate box around Y to align X to XY plane of Plane). then i just run script second time and box didn’t rotate. So i can’t understand what error did you mention?
if it possible could you share matrix3 values for 2 objects and what axis align to what plane. and i’ll try it out.
everything is much easier:
fn alignAxisToDir node axis:#z dir:[0,0,1] =
(
vec = case axis of
(
#x: node.transform[1]
#y: node.transform[2]
#z: node.transform[3]
)
tm = node.transform
vec = normalize vec
dir = normalize dir
rtm = angleaxis (acos (dot vec dir)) (normalize (cross dir vec))
node.transform = translate (rotate (scalematrix tm.scale) (tm.rotation*rtm)) tm.pos
)
just needed to think a little more
PS. … and a little more
fn rotMatrix v a = (quat (v.x*(sin (a/2))) (v.y*(sin (a/2))) (v.z*(sin (a/2))) (cos (a/2))) as matrix3
But it will be clockwise. use inverse quat to counterclockwise rotation.
Something wrong with your makeRotateMatrix – makeRotateMatrix [1,0,0] 0 returns:
(matrix3 [1,0,0] [0,0,-1] [0,1,0] [0,0,0])
UPDATE:
I made align with matrices on 1st page. Could you please help doing it with quat?
I find projection with plane with cross product? then make quat to rotate axis in that projection and decide wich way to rotate using cross product of axis and its projection. if result equals to axis of rotation then don’t change quat. if no – inverse it.
But due to rounding errors and some strange things when max returns false on equal values it has too many lines. Maybe you’ll find shorter way.
I’ll take a look at some of these new developments a little later on… for the time being, all the rotating has made me dizzy
i don’t see any axis aligned:
(
delete objects
s = point name:"s" axistripod:on constantscreensize:on isselected:on
t = plane name:"t"
rotate s (eulerangles 33 25 17)
tm1 = s.transform
tm2 = t.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 s rQuat
)
it’s why I’ve asked about that…