[Closed] Rotate TM to match another TM
How do I go about calculating the offset in order to rotate and position an objects TM to match that of another.
And no it’s not as simple as tmA = tmB.
I need it to rotate tmA to match that of tmB.
(matrix3 [0.316467,-0.74223,0.590714] [-0.717996,0.219547,0.660516] [-0.619944,-0.633162,-0.463439] [0,0,0])
(matrix3 [1,0,0] [0,1,0] [0,0,1] [0,0,0])
A * (inverse A) = Identity Matrix
Given matrices A, B, find matrix C:
From linear algebra:
A*C=B
C=(inverse A)*B. …but then heirarchies complicate things– they need to be in the same coordinate space– you need to find the common ancestor. Transform A and B into that common space and then I think you can find your matrix C.
…look at the xformMat command to transform a matrix into the coordinate space of another.
There are no heirarchies in this case. Just 2 simple nodes in the scene. And all I want to do is rotate the one node to match the other.
Ok… after re-reading your post above, I think I misunderstood your intent– if I now understand correctly… you have two nodes in the scene that are oriented differently and are not co-located… and you want to rotate node A into the position and orientation of node B?
If this is the case, then would this be the correct processb[/b]:
- Get vectors from origin to each node and normalize (nVecA, nVecB):
nVecA = normalize A.pos
nVecB = normalize B.pos
- Take cross product of these normalized vectors to get the axis of rotation to rotate node A into node B:
theAxis = cross nVecA nVecB
- Use the dot product to get the amount of rotation:
theAngle = acos(dot (nVecA) (nVecB))
- Now you have angle and axis– convert this to quat:
quatA2B = (angleaxis theAngle theAxis) as quat
-
Rotate node A’s position into node B’s position using: <point3> * <quat> (may need to scale this position by the ratio of the distances (from the origin) of nodes A and B over the number of frames to end up at node B’s position).
-
For the orientation… couldn’t you simply animate setting node A direction property (A.dir) equal to node B’s direction property B.dir (this will align the local z axes)??? And likewise choose the other axis (either X or Y) to align and just animate setting that matrix row of A equal to the same row in B???
Interesting question… I hope I haven’t steered you down a wrong path. I will play with this when I get home from work today to see if what I said was accurate.
If you have the transforms for nodes A and B then try:
A * C = B
C =( inverse (A.transform.rotationpart as matrix3) ) * ( B.transform.rotationpart as matrix3 )
Then when you multiply A * C to orient A to B it should leave node A in it’s current position since the translation rows are set to zero in the above.
I don’t have access to 3ds Max to verify right now, but… I believe you could leave the rotations as Quats and use the preRotate maxscript command as well…
preRotate <matrix3> <quat>
[left]Applies an incremental rotation transformation to the input matrix or matrices. This is equivalent to multiplying on the LEFT by the transform. If the matrix3 parameter is a single matrix, this function returns the transformed matrix. If the parameter is an array of matrices, this function returns the value OK. In both cases, the input matrix3 value(s) are replaced with the transformed matrix value(s).[/left]
tempTM = preRotate A.transform ( B.transform.rotationpart * ( inverse A.transform.rotationpart ) )
A.transform = tempTM
Or also, the Rotate command and switching the order of the quats should give the same results…
tempTM = Rotate A.transform ( ( inverse A.transform.rotationpart ) * B.transform.rotationpart )
A.transform = tempTM
I’m not sure I’ve been of any help… but as you probably know, internally rotations are stored differently than what you see in the scene. See the attached primer on 3dsMax Rotations written by Kees Rijnen.
[font=Courier New][/font]
here is a function I wrote to match the pos /rot of obj to target.
perhaps you can adat it to your needs.
It is based on Bobo’s video the Matrix Explained
( which can be found inyou tube installments )
the challenge is that , while positon xyz is simply encoded in row 4 of a matrix ,
the scale rotation data is mingled and scattered between rows 1-3,
so to avoid matching the scale you have to replace the scale part of the target transform
with the scale part of the object transform.
fn matchPosRot obj target = (
t=target.transform
--we don't want the scale copied, so remove target scale info
tScale=t.scalepart
t.row1 /= tScale.x
t.row2 /= tScale.y
t.row3 /= tScale.z
--replace with obj scale info
oScale=obj.transform.scalepart
t.row1 *= oScale.x
t.row2 *= oScale.y
t.row3 *= oScale.z
--comment the line below to remove translation info , keeping only rotation
t.row4 = target.transform.row4
obj.transform = t
)
Correct. I have two nodes in which I want to rotate,move,scale node A to match node B.
But do you care if node A linearly interpolates to node B in regards to position? Or do you want it to arc into node B?
Maybe this would work for translating A into B??? Just thinking out loud as I’ve never tried this (…and like I said, I’m not at 3ds Max to verify)…
What if you took the normalized position vector from the origin of each node and turned them into a quat with W = 0.
nVecA = normalize A.pos
nVecB = normalize B.pos
quatA = quat nVecA.x nVecA.y nVecA.z 0
quatB = quat nVecB.x nVecB.y nVecB.z 0
numFrames = ???
Could you then SLERP the position of node A into node B using:
slerp quatA quatB numFrames
converting each intermediate quat value back to a point3 position (again W = 0) ???
It can be an instant thing as well. It does not have to happen over the course of time.
Are you doing anything to the nodes’ geometry object? i.e., offseting it from the pivot or manipulating the object with modifiers (e.g., bend, taper, FFDs, etc.)? Or do you only care to operate on the node transforms?
How do you want to affect the change to node A’s transform? You stated it wasn’t as simple as saying: nodeA.transform = nodeB.transform… (<– why isn’t it that simple? Because that captures position, rotation, and scale all at once) …you said that you needed to rotate node A to match node B. Can you explain in more detail?
Or is this a single match TM operation (like, something to be achieved by a custom attribute button press that would match node A to node B any time the button is pressed?) or do you want node A to follow along with node B for some amount of time?
Correct. I have two nodes in which I want to rotate,move,scale node A to match node B.
yeah, I’m confused what you are asking now, because the above sounds like
A.transform = B.transform
Is it possible you are speaking not of matching object transforms, but of matching one object’s pivot point to another, while leaving the geometry in place?
If this is what you need to do, it should be possible with tmA = tmB.
(
delete objects
objA = box height:100
objB = box height:100
objA.name = "objA"
objB.name = "objB"
objA.wirecolor = green
objB.wirecolor = red
tmA = matrix3 [0.316467,-0.74223,0.590714] [-0.717996,0.219547,0.660516] [-0.619944,-0.633162,-0.463439] [0,0,0]
tmB = matrix3 1
objA.transform = tmA
objB.transform = tmB
objA.transform = objB.transform
)
However, you stated that it wouldn’t be possible using equality, so I suppose the issue is that some of the nodes TM whas reseted at some point, as in the following example:
(
delete objects
objA = box height:100
objB = box height:100
objA.name = "objA"
objB.name = "objB"
objA.wirecolor = green
objB.wirecolor = red
tmA = matrix3 [0.316467,-0.74223,0.590714] [-0.717996,0.219547,0.660516] [-0.619944,-0.633162,-0.463439] [0,0,0]
tmB = matrix3 1
objA.transform = tmA
objB.transform = tmB
resetxform objA
objA.transform = objB.transform
)