[Closed] moving an object along local axis?
i have 2 points linked to a 3rd the parent is rotated in space. i want to use a slider to move the two children along their local y axis i do this bu taking the value of the slider, and adding it to the position of the parent, this value is the new position of the point. what it does though is move the point in WORLD Y whcih means the points do not stay truly aligned.
is there away to force the point to move along its own local axis instead of world?
I believe you are looking for the in coordsys prefix for the translate
in coordsys #local $.pos.y += moveValue
thanks blue it kind of works but what its doing now is continually adding to the position of the points regardless of the slider value…
this is an example of what i have. i stored the points in an array so i can find them easily…
in this example, point[2] is a child of point[1]
point[2].pos.y = (point[1].pos .y + slidervalue)
now this works in that the slider has a 0 point to reset the point to… however as soon as i use the in coordsys #local its continually adds to the position no matter which way i move the slider…
Ya you can’t just do += slidervalue, if you want a reletive slider like that you need to do something most along the lines of +=(sliderVal-theLastSliderVal). So you need to store the last value of the slider and when you are done return the slider back to 0. Does that make sense?
As far as I remember grant adam did a script like this called “super tti” or “super transform type in” which gave you local and world space position rotation and scale. As Paul mentioned if you use local coordinates you’ll notice that your transform type in always reads 0 for everything – an objects local coordinates can never be anything aside from 0,0,0 – it’s just the orientation of it’s axis that are being provided as a convenience.
If you think about it, if you set a local x position of 10, that means that an object is becoming offset from its current position [0,0,0] by 10 units. As soon as this happens, the place where the object has moved to becomes its new local coordinate of [0,0,0]. Say for example you make a slider that uses a += command to offset the object in its local space and lets say for the sake of simplicity it uses integers so we’re only dealing with whole numbers. Say we drag the slider of the x axis up to 3 what is happening is that each time the number of the spinner changes, the position of the object evaluates and the viewport updates. So lets say our spinner goes from 0 to 1, 1 to 2 and 2 to 3. Rather than max just keeping this as an offset of 3 along the local axis of the object it treats it as follows:
Object starts at 0 on the x.
Offset of 1 is applied to the object, object moves 1 unit to the right, local coordinates get updated and put back to 0.
Offset of 2 is applied to the object, object moves 2 units to the right, local coordinates get updated and put back to 0.
Offset of 3 is applied to the object, object moves 3 units to the right, local coordinates get updated and put back to 0.
In effect since the object has actually become offset by 6 units rather than the 3 that you’d expect. this is because max is continually updating the spinner and each time applying a new offset to the object rather than waiting for you to release the spinner and apply the number in the spinner field once and once only.
Realistically what you want to do is tell maxscript to only apply the offset of the object once. There’s probably tonnes of ways to do this but heres one or two ideas:
-
When you activate the ui of the offset controls, use a callback to get the selected objects current position and hold it as a variable. Lets call this variable $original_pos. Now each time the spinner on changed val command is called tell it to set the position of the object to $original_pos + the spinner value. This will cancel out the objects local position being continually evaluated and make sure the object moves the amount specified in the spinner and no more. Maybe use an on mouse up command on the spinner (not quite sure of the exact event handler) so that when the mouse stops using the spinner the $original_pos variable gets updated to reflect the new position.
-
Pretty much the same idea but set the $original_pos variable to the selected objects position when the spinner is first clicked on.
I’ve never actually coded this myself so the execution mightnt work as above but the theory should be sound behind it – Paul, Bobo and the others that know better feel free to jump in and make corrections.
I wasn’t suggesting the example to be used on a changed return of the slider value and I didn’t feel it was necessary for to write the script to get the point across but here it goes. I hope this clears up the confussion on at least one way to use in coordsys #local with sliders.
-- start of move local example
global mLROLL
(
local mLPOS
local mLOBJ
local mLXVal = mLYVal = mLZVal = 0
try(DestroyDialog mLROLL)catch()
rollout mLROLL "Move Selected Locally" width:300 height:400
(
slider mLX "X:" type:#float range:[0,100,0]
slider mLY "Y:" type:#float range:[0,100,0]
slider mLZ "Z:" type:#float range:[0,100,0]
pickbutton mLPBTN "Pick Object to Move Locally"
on mLX changed value do
(
in coordsys #local mLOBJ.pos.x = mLPOS.x + mLX.value - mLXVal
mLXVal = mLX.value -- store the slider val
)
on mLY changed value do
(
in coordsys #local mLOBJ.pos.y = mLPOS.y + mLY.value - mLYVal
mLYVal = mLY.value -- store the slider val
)
on mLZ changed value do
(
in coordsys #local mLOBJ.pos.z = mLPOS.z + mLZ.value - mLZVal
mLZVal = mLZ.value -- store the slider val
)
on mLPBTN picked obj do
(
mLOBJ = obj
mLPOS = mLOBJ.pos
in coordsys #local mLOBJ.pos = (mLPOS + [mLX.value,mLY.value,mLZ.value])
mLXVal = mLX.value -- store the slider val
mLYVal = mLY.value -- store the slider val
mLZVal = mLZ.value -- store the slider val
)
)
createdialog mLROLL style:#(#style_minimizebox, #style_titlebar, #style_sysmenu, #style_border)
)
-- end of move local example
Code block messed up the formatting and broke some variables in half so posting as text. I'd rather loose the tabbing than the functionality.
Hey Dave,
I was trying out in max:
Point02 is a child of Point01
Freeze Transform on Point02.
Wire the Zero’d Point02 Y to a slider.
It translates in local Y space, and yet also rotates when Point01 the parent moves/rotates. Is this what you are looking for?
sounds like it gallenwolf. i will have a look into that tommorow. cheers!!!
gallenwolf. this might be a silly question but how are you freezing the transforms? also are you wiring it via parameter wiring to a slider in the viewport or a maxscript slider?
Hiya,
To freeze transforms, select an object, hold down ALT then right-click in the viewport.
I tried both, wiring to a Slider Manipulator, as well as using the Parameter Editor to create a spinner. Do post if you need more help.