Notifications
Clear all

[Closed] Align an axis to a plane, using other axis?

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

 3ak

i run my fn on already aligned box and nothing changes. what is incorrect?

3 Replies
(@denist)
Joined: 11 months ago

Posts: 0

what axis your function does align?

 3ak
(@3ak)
Joined: 11 months ago

Posts: 0

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.

(@denist)
Joined: 11 months ago

Posts: 0

i didn’t…

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

 3ak

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

 3ak

oops. my bad than)

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…

Page 3 / 4