maxscript performance
Use bitarrays instead of arrays when possible
example from maxscript doc (split a mesh by uv elements)
fn split_mesh_by_uv_shell node channel = (
local ob = copy node
converttomesh ob
while ob.numfaces > 0 do (
face_array = #(1)
cnt = 0
while cnt < face_array.count do (
cnt += 1
-- get data one by one, too much meshop operation
map_verts = meshop.getmapvertsusingmapface ob channel #(face_array[cnt])
map_faces = meshop.getmapfacesusingmapvert ob channel map_verts
-- finditem is slow
for f in map_faces where finditem face_array f == 0 do (
append face_array f
)
)
local shell_emesh = editable_mesh()
shell_emesh.mesh = meshop.detachfaces ob face_array delete:true asmesh:true
shell_emesh.transform = node.transform
shell_emesh.name = uniquename (node.name +_uvshell)
)
delete ob
)
optimized version
fn split_mesh_by_uv_shell node channel = (
local ob = copy node
converttomesh ob
while ob.numfaces > 0 do (
-- use bitarray
local shell_faces = #{1}
local work_faces = #{1}
while not work_faces.isempty do (
-- get data using bitarray at a single meshop function
local map_verts = meshop.getmapvertsusingmapface ob channel work_faces
local work_faces = (meshop.getmapfacesusingmapvert ob channel map_verts) - shell_faces
-- we can add bitarray using + operator, which is much faster then append
shell_faces += work_faces
)
local shell_emesh = editable_mesh()
shell_emesh.mesh = meshop.detachfaces ob shell_faces delete:true asmesh:true
shell_emesh.transform = ob.transform
shell_emesh.name = uniquename (node.name +_uvshell)
)
delete ob
)
old | optimize version | |
---|---|---|
1k | 108 ms | 86 ms |
10k | 1741 ms | 152 ms |
20k | 8654 ms | 314 ms |
50k | 43148 ms | 516 ms |
Another advantage of using bitarray, we can process values easier and it\'s pretty fast
union: A + B
subtract: A - B
intersect: A * B
Disable viewport redraws when making changes to scene objects
Use redraw context
with redraw off (
-- your code here
)
Use redraw disable function
disablesceneredraw()
-- your code here
enablesceneredraw()
Disable max redraw by sending message to max main window hwnd
windows.sendmessage (windows.getmaxhwnd()) 0x000B 0 1
-- your code here
windows.sendmessage (windows.getmaxhwnd()) 0x000B 0 0
redraw context is the preferred one, because we have to ensure our code will not throw any exception before we re-enable redraw, which will freeze max ui.
Usually, by disabling redraw we can only get tiny performance improvement, so safety first 😉
Disable Undo system when possible
two way of undo context:
with undo on (
-- your code here
)
-- we can also use undo with redraw context
with undo off redraw off (
-- your code here
)
undo undo label on (
-- your code here
)
Modify Panel can be slow - change to Create Panel when possible
Some operations on scene objects will reevaluate the modifier stack and also force an update of the Command Panel UI. Even if the viewport redraws are suppressed, the Modify Panel might be forced to redraw. When the modifier stack is not needed by the script (for example for setting Sub-Object levels etc.). Here are two methods to disable ui redraw.
Switch to create mode
max create mode
Disable modifier panel
suspendEditing()
-- your code here
resumeEditing()
It seams good to avoid useless update of ui, but in some case we have to update modifier panel to ensure our script work !!!!!
such as editing vertex noraml, using morph modifier, it pretty weird.