[Closed] Relax along Z axis
I was searching for a solution how to relax along Z axis only and found this thread:
https://forums.cgsociety.org/t/zlax-relax-along-z-value-only/1246777
Unfortunately, none of the two options provided in the thread worked for me.
Could someone check the script and help with a working code?
- If you select an editable poly, then the script runs on all the verts
- If you are in sub-object then it runs on the selected verts only
fn relaxPolyVertsUsingAxis node verts: amount:0.5 iterations:10 keepBorder:off keepOuter:off axis:#z =
(
if verts == unsupplied or verts == #all do verts = #{1..node.numverts}
if verts == #selected do verts = node.selectedverts as bitarray
node.setSelection #vertex verts
getvert = polyop.getvert
pp = for v in verts collect (getvert node v)
node.relaxAmount = amount
node.relaxIterations = iterations
node.relaxHoldOuterPoints = keepOuter
node.relaxHoldBoundaryPoints = keepBorder
node.relax selLevel:#vertex
_axis = case axis of
(
#x: #{1}
#y: #{2}
#z: #{3}
#xy: #{1,2}
#yz: #{2,3}
#xz: #{1,3}
default: #{1..3}
)
k = 0
for v in verts do
(
k += 1
p = getvert node v
for i in _axis do pp[k][i] = p[i]
)
polyop.setvert node verts pp
update node
)
Do I need to run relaxPolyVertsUsingAxis() with some parameters?
Didnt manage to run it
does this part mean this script supports relax along all these axis?
/************************ example setup *********/
delete objects
gc()
n = plane name:#relax_poly_test width:100 length:100 widthsegs:32 lengthsegs:32
addmodifier n (Noisemodifier strength:[2,2,10] fractal:on roughness:1 scale:10)
converttopoly n
relaxPolyVertsUsingAxis n verts:#all amount:0.5 iterations:20 keepBorder:on keepOuter:off axis:#z
-- relaxPolyVertsUsingAxis n verts:#all amount:0.5 iterations:20 keepBorder:on keepOuter:off axis:#xy
you can specify relax parameters, axis to relax effective, and vertex selection … It works for editable poly, but it can be easily changed to work with editable mesh. And you are free to do it
ps. of course I could forget something but the idea is clear enough
I noticed that if I run relaxPolyVertsUsingAxis $
it uses the values defined at the top,
is there a reason why default values are defined in advance if you’re going to run the function with values anyway? eg relaxPolyVertsUsingAxis n verts:#all amount:0.5 iterations:20 keepBorder:on keepOuter:off axis:#z
optional arguments are defined with default values in case if you don’t need to change all of them every call… it’s a common practice
All right, my brain reached melt-down.
Time for some relaxation!
One hour later, I ended up with nothing more than a tiny UI
If anyone is in the mood to finish this one, I give you a big thank you in advance!
rollout Relaxer "Time to relax with denisT" width:210 height:200
(
slider 'slider_amount' "Amount:" pos:[10,15] width:200 height:44 range:[0.05,1,0.5] align:#left
editText 'amount_value' pos:[60,15] width:50 height:15 align:#left
slider 'slider_iteration' "Iteration:" pos:[10,70] width:200 height:44 range:[1,100,10] align:#left
editText 'iteration_value' pos:[60,70] width:50 height:15 align:#left
label 'lbl_axis' "Smooth axis" pos:[10,120] width:40 height:15 align:#left
checkbox 'chk_x' "x" pos:[60,120] width:29 height:15 align:#left
checkbox 'chk_t' "y" pos:[100,120] width:29 height:15 align:#left
checkbox 'chk_z' "z" pos:[140,120] width:29 height:15 align:#left
checkbox 'chk_outer' "Keep outer" pos:[114,140] width:77 height:15 checked:true align:#left
checkbox 'chk_border' "Keep border" pos:[12,140] width:82 height:15 checked:true align:#left
button 'btn_relax' "Relax" pos:[51,168] width:80 height:21 align:#left
on slider_amount changed val do
(
-- the slider caption changes amount_value text to match slider_amount
)
on amount_value entered text do
(
-- if this changes, it changes the slider_amount value
)
on slider_iteration changed val do
(
-- the slider caption changes iteration_value text-field
)
on iteration_value entered text do
(
-- if this changes, it changes the slider_iteration value
)
on btn_relax pressed do
relaxPolyVertsUsingAxis $ verts:#all amount:0.5 iterations:20 keepBorder:on keepOuter:off axis:#z
)
fn relaxPolyVertsUsingAxis node verts: amount:0.1 iterations:10 keepBorder:off keepOuter:off axis:#z =
(
if verts == unsupplied or verts == #all do verts = #{1..node.numverts}
if verts == #selected do verts = node.selectedverts as bitarray
node.setSelection #vertex verts
getvert = polyop.getvert
pp = for v in verts collect (getvert node v)
node.relaxAmount = amount
node.relaxIterations = iterations
node.relaxHoldOuterPoints = keepOuter
node.relaxHoldBoundaryPoints = keepBorder
node.relax selLevel:#vertex
_axis = case axis of
(
#x: #{1}
#y: #{2}
#z: #{3}
#xy: #{1,2}
#yz: #{2,3}
#xz: #{1,3}
default: #{1..3}
)
k = 0
for v in verts do
(
k += 1
p = getvert node v
for i in _axis do pp[k][i] = p[i]
)
polyop.setvert node verts pp
update node
)
createdialog Relaxer style:#(#style_toolwindow, #style_sysmenu)
/************************ example setup ******
delete objects
gc()
n = plane name:#relax_poly_test width:100 length:100 widthsegs:32 lengthsegs:32
addmodifier n (Noisemodifier strength:[2,2,10] fractal:off roughness:1 scale:10)
converttopoly n
*****************************************/
try(destroydialog PolyRelaxByAxis) catch()
rollout PolyRelaxByAxis "Relax by Axis" width:191
(
fn relaxPolyVertsUsingAxis node verts: amount:0.5 iterations:10 keepBorder:off keepOuter:off axis:#z =
(
old_sel = node.selectedverts as bitarray
if verts == unsupplied or verts == #all do verts = #{1..node.numverts}
if verts == #selected do verts = node.selectedverts as bitarray
node.setSelection #vertex verts
getvert = polyop.getvert
pp = for v in verts collect (getvert node v)
node.relaxAmount = amount
node.relaxIterations = iterations
node.relaxHoldOuterPoints = keepOuter
node.relaxHoldBoundaryPoints = keepBorder
node.relax selLevel:#vertex
_axis = case axis of
(
#x: #{1}
#y: #{2}
#z: #{3}
#xy: #{1,2}
#yz: #{2,3}
#xz: #{1,3}
default: #{1..3}
)
k = 0
for v in verts do
(
k += 1
p = getvert node v
for i in _axis do pp[k][i] = p[i]
)
polyop.setvert node verts pp
node.setSelection #vertex old_sel
update node
)
group "Relax: "
(
spinner amount_sp "Relax Value: " range:[0,1,0.5] type:#float scale:0.01 \
fieldwidth:56 align:#right offset:[4,0] tooltip:"Relax Amount"
spinner iterations_sp "Iterations: " range:[1,1000,10] type:#integer \
fieldwidth:56 align:#right offset:[4,0] tooltip:"Relax Iterations"
checkbox keep_boundary_ch "Keep Boundary" checked:on offset:[0,4]
tooltip:"Keep Boundary"
checkbox keep_outer_corners_ch "Keep Outer Corners" checked:off offset:[0,0]
tooltip:"Keep Outer Corners"
)
group "Axis: "
(
radiobuttons axis_rb labels:#("X", "YZ", "Y", "XZ", "Z", "XY", "XYZ") default:7 columns:2 align:#left offset:[40,0] \
offsets:#([0,0],[-41,0],[0,5],[-41,5],[0,10],[-41,10],[54,15])
)
group "Vertex: "
(
radiobuttons target_rb labels:#("All", "Selected") columns:2 align:#left offset:[40,0] offsets:#([0,0],[-5,0])
)
group ""
(
button relax_bt "Relax" width:173 align:#left offset:[-4,-7]
)
on relax_bt pressed do undo "Relax" on if iskindof (node = selection[1]) Editable_Poly do
(
axis = uiaccessor.getwindowtext axis_rb.hwnd[axis_rb.state] as name
verts = uiaccessor.getwindowtext target_rb.hwnd[target_rb.state] as name
relaxPolyVertsUsingAxis node verts:verts \
amount:amount_sp.value \
iterations:iterations_sp.value \
keepBorder:keep_boundary_ch.state \
keepOuter:keep_outer_corners_ch.state \
axis:axis
)
on PolyRelaxByAxis close do
(
)
on PolyRelaxByAxis open do
(
)
)
createdialog PolyRelaxByAxis
this is the UI of the tool might look like. I already showed in other my posts how to make it the real tool –
# save dialog position (and state)
# save/load settings on dialog open/close
# save/load settings between MAX sessions
# make it a macrobutton
# organize as one struct (one script, one file)
technically it should be a modifier.
If I have time I will show how to make it a Modifier
I think options are always good.
Making it a scripted modifier sounds like a very good idea since it is non-destructable – but the UI you made is also good because I believe it gives users an option to choose.