[Closed] Align two objects without using their pivots
I would like to align two objects without using their pivots.
The two objects are guaranteed to be identical in their mesh, or almost identical, but their pivot are totally unreliable since they were detached and attached multiple times.
I want to align source to target, matching their position, rotation and scale. For scale and position it’s easy. But for rotation…
The idea is to pick three points located at the same relative place on both objects. Then define two matrices from these points. But then I don’t know how to get the rotation from matrix1 to matrix2, in order to apply this rotation to source.
Here is my code so far :
fn pointLineProj pA pB pC =
(
local vAB=pB-pA
local vAC=pC-pA
local d=dot (normalize vAB) (normalize vAC)
(pA+(vAB*(d*(length vAC/length vAB))))
)
SourceObj = $source
TargetObj = $target
A1 = $A1.pos
B1 = $B1.pos
C1 = $C1.pos
A2 = $A2.pos
B2 = $B2.pos
C2 = $C2.pos
xAxis1 = A1-B1
yAxis1 = (pointLineProj B1 A1 C1) - C1
xAxis2 = A2-B2
yAxis2 = (pointLineProj B2 A2 C2) - C2
scaleRatio = (length Line2)/(Length Line1)
posOffset = A2 - A1
sourceX = normalize xAxis1
sourceY = normalize yAxis1
sourceZ = normalize (cross sourceY sourceX )
sourceTransform = matrix3 sourceX sourceY sourceZ A1
sourceQuat = sourceTransform as quat
targetX = normalize xAxis2
targetY = normalize yAxis2
targetZ = normalize (cross targetY targetX )
targetTransform = matrix3 targetX targetY targetZ A2
targetQuat = targetTransform as quat
sourceObj.rotation *= sourceQuat
I just made a script somewhat recently that does this, I think. I was doing it for the same kinda reasons. Although I don’t take into account scale, to match it I mean.
I did it a simpler way. But similar. The User has a Mesh selected, Clicks 2 times per Mesh, which Creates Point Helpers between the 2 clicks, with its Local Z along the Face Normal, and it’s X,Y computed for the angle between the 2 clicks and the face normal.
Then I just get the transform of the destination point helper and set my current one to that.
My question would then be : How do you get the transform from A to B ?
I just did something like, A.Transform = B.Transform on the point helper.
Oh, and I forgot the biggest thing. To make it easy on myself and the script, instead of trying to figure out all the rotation stuff and whatnot, I just linked the selected mesh to the point helper, then set that Transform the other one, and deleted both.
That way, I am not actually changing the transform with my own code, but max does it internally.
Yes I just had the idea to link the object to the helper, makes it easier
Anyway I just can’t do Helper.transform = Newtransform, the two objects just don’t match…
I tried with Helper.transform *= NewTransform, but it still doesn’t match, albeit in a different way…
Nice. Yes, I ran into that as well. Sometimes the rotation is wrong on the X,Y. Gets rotated 45 or 90 the wrong way. But if you clicked the same spots on both meshes, and computed the transforms the same, it should line up.
But that is a tough one… Might be a way to align them like I said, then do some if/then states to check the X,Y to see if they are lined up or not, and if not, see how far they are off and rotate? But that’s getting back into the realm u were just in.
This should do it (assuming that the objects haven’t been scaled non-uniformly):
(
-- compute matrix from A1,B1 and C1
v1_ab = $B1.pos - $A1.pos
n1_ab = normalize v1_ab
n1_ac = normalize ($C1.pos - $A1.pos)
u1 = normalize (cross n1_ab n1_ac)
v1 = normalize (cross n1_ab u1)
m1 = matrix3 u1 v1 n1_ab $A1.pos
-- compute matrix from A2,B2 and C2
v2_ab = $B2.pos - $A2.pos
n2_ab = normalize v2_ab
n2_ac = normalize ($C2.pos - $A2.pos)
u2 = normalize (cross n2_ab n2_ac)
v2 = normalize (cross n2_ab u2)
m2 = matrix3 u2 v2 n2_ab $A2.pos
-- scale second matrix based on difference in
-- distance between A1-B1 and A2-B2
-- (obviously doesn't work if objects are scaled non-uniformly)
d = length v2_ab / length v1_ab
scale m2 [d,d,d]
-- set new transform of source object
$Src.transform = ($Src.transform * inverse m1) * m2
)
Hope this helps,
Martijn