Notifications
Clear all

[Closed] Keying transforms on linked objects with script

I’m developing headaches trying to use Maxscript to key animated transforms on linked objects. I find that anytime I set the ‘$.transform’ of a linked object, the object jumps to an undesired location. What is really going on?

MAX help makes an attempt on explanation – not elaborate. I’m not experienced in Matrix3. I’ll appreciate some layman’s explanation to what MAX is doing with the transform matrices and why rotation has to affect position?

SITUATION:
I have a big box ‘A’ @ [0,0,0] and two smaller ones ‘B’ @[-50,0,0] and ‘C’ @[-100,0,0]. BC are linked to A. With the autokey on, I rotate ‘A’ at frame 10. I rotate ‘B’ (still at frame 10) to another orientation. When I scrub the timeslider all objects rotate (as linked) with ‘C’ transforming about ‘A’ naturally. HOW DO I script a change in C’s orientation to match ‘B’s direction @ frame 10, without affecting the inherited position?

7 Replies

Check the “Node Transform Properties” section of the MAXScript Reference. At the bottom you will find:

– Setting a node’s rotation relative to world space without
– messing with its position:
fn setNodeWorldRotation theNode theRot =
(
in coordsys (transmatrix theNode.transform.pos)
theNode.rotation = theRot
)

setNodeWorldRotation $ (eulerangles 45 45 0)
-Eric

OOooo:eek: How did I miss that?

More, … You’ve shown me something too: “In Coordsys” Context!
Thanks a lot!

And look at “in coordsys parent” too. That may be all you need.

🙁 Guys!

Its from one problem to another. While the “In Coordsys” context solved my rotation problems, Maxscript is giving me headaches as I script (animated keys) positional changes. Vector maths is not producing expected results.

What is the Matrix3 all about and how do I use it?

SITUATION:

Trying to copy an object’s pose (pos, rotation, scale) to another location at another time and have MAX animate the movement between the positions. $.pos=oldpos+vector difference is not working.

 eek

OK, well thats easy enough. A matrix3 is a 3X4 matrix containing 4 vectors: x y z w. Each vector determines an axis in world space from the origin – the 4th ‘w’ axis determines its offset from the world origin, or in other words its positions.

The first three x y z vectors determine the rotation of the object and the scale – the scale is derived from the ‘unit length’ of each vector. I.e if the distance from each x,y,z vector to the origin is equal to 1 then the scale is 100%. If the x vectors length is more than 1 then your essentially scaling the object along its x axis.

Ontop of this is the fact that each axis’ has to be ‘orthogonally’ correct – that means 90 degree perpendicular to each other. When there not, is when you get skewing – this is perticulary preverlant if you scale and object along one axis, parent another object to it and rotate it – your see the child object skewing.

Now you said you just want position to change over time, lets deal with this first by getting the two positions.

Trying to copy an object’s pose (pos, rotation, scale) to another location at another time and have MAX animate the movement between the positions. $.pos=oldpos+vector difference is not working.

This you know, will make the object stay still between those frames.

 ( 
local basePos = $.pos
with animate on
(
	 for f = 20 to 30 do
	 (
	 slidertime = f
	 $.pos = basePos
	 )
)
)

If you want an object to blend between two positions over a time range then its just a case of linear interpolation:

 ( 
local firstPos = [10,10,10] -- your first pose
local secondPos = [20,20,20] --second pose
local timeStart = 10
local timeEnd = 20
local t = 0.0
 
for f = timeStart to timeEnd do
(
slidertime = f
t = ((((slidertime as integer / 160) as float)-timeStart)/(timeEnd-timeStart))
$object.pos = (1-t)*firstPos + t * secondPos
)
)

Essentially with linear interpolation, where getting two values and blending them together – but more importantly blending them together in a range. So when we get the time range with 10f, 20f and current time (slidertime)

Then what we do is take the current time from the start time so (15-10) = 5 and then the end time from the start time (20 – 10) = 10 now all we do is divide 5/10 = 0.5. And as this is happening over time I.e slidertime ‘f’ is fn of the equation we get the blend over time.

Now if the object you want to ‘pin’ is parented your’ll have to put it into world space

$.transform.pos = (1-t)*firstPos + t * secondPos

And if you want to keep its offset difference i.e its current position in relation to the two target positions. Your have to firstly get the ‘space’ its working into relative to the first position.

offsetPos = ($.pos – [10,10,10])

and then add this on to its position for each frame.

OK, well thats easy enough. A matrix3 is a 3X4 matrix containing 4 vectors: x y z w. Each vector determines an axis in world space from the origin – the 4th ‘w’ axis determines its offset from the world origin, or in other words its positions.

The first three x y z vectors determine the rotation of the object and the scale – the scale is derived from the ‘unit length’ of each vector. I.e if the distance from each x,y,z vector to the origin is equal to 1 then the scale is 100%. If the x vectors length is more than 1 then your essentially scaling the object along its x axis.

Ontop of this is the fact that each axis’ has to be ‘orthogonally’ correct – that means 90 degree perpendicular to each other. When there not, is when you get skewing – this is perticulary preverlant if you scale and object along one axis, parent another object to it and rotate it – your see the child object skewing.


That was a needed explanation.
However, the sample code embedded didnt work. Maybe a parenthesis omission. Can you throw more light on the following?

t = ((timeStart -((slidertime as integer/160) as float))/(timeEnd-TimeStart))
     $object.pos = (1-t)*firstPos + t * secondPos
 
 eek

yeah it should be the slidertime minus the start time divided by the endtime – the start time. Or in other words the duration/range:

(((slidertime as integer / 160) as float)-timeStart)/(timeEnd-timeStart)

It didnt work because before we were dividing a negative value by a positive. So or intance start = 10, end = 20, current time = 15 would be 10-15 = -5 / 10 = -0.5. A way to fix it would be to add a abs() (absolute) to force it into being positive.

abs((((slidertime as integer/160) as float)-timeStart)/(timeEnd-timeStart))

cheers,

P.s I edited my original post and Im writting this without max in front of me so, can be a little tricky.