ProOptimizer Script help

ProOptimizer Script help

james_murphieJ25KK
Explorer Explorer
2,392 Views
7 Replies
Message 1 of 8

ProOptimizer Script help

james_murphieJ25KK
Explorer
Explorer

Hi there,

 

I want to create a script that will apply ProOptimiser modifier to the selected object, calculate how many faces the selected object has and then automatically adjust the optimization level until the number of faces is 64000 or less. So far this is the working Maxscript that I have.

 

macroScript ApplyProOptimizer
category:"My Scripts"
tooltip:"Apply ProOptimizer and Optimize to 64,000 Faces"
(
modPanel.addModToSelection (ProOptimizer ()) ui:on
$.modifiers[#ProOptimizer].Calculate = on
)
 
 
The trouble I am having is with adjusting the optimization level, if anyone can help out that would be much appreciated! Thank you.
0 Likes
Accepted solutions (1)
2,393 Views
7 Replies
Replies (7)
Message 2 of 8

MartinBeh
Advisor
Advisor

For some reason $.modifiers[#ProOptimizer].vertexCount = 64000 works in the MAXScript listener but does not update when called from a piece of MAXScript code...

 

From what I see the ProOptimizer modifier has one subanim which can carry a controller and contains the current vertex percentage.

Here is some quick code do iterate ProOptimizer percentage until vertex count is below some threshold:

(  -- M. Breidt (22.03.2025) - reduce ProOptimizer percentage until vertex count is reached
	obj = selection[1]
	p = 100.0				-- start percentage
	desiredCount = 64000		-- how many vertices should be left?
	vCount = 0

	m = ProOptimizer()
	addModifier obj m
	m.calculate = true

	format "Trying to get below % vertices\n" desiredCount
	do (
		m[1].value = p
		-- vCount = m.vertexcount 	-- this is not updating correctly within the loop...
		vCount = obj.numverts	-- .. so we use the mesh vert count
		format "% percent -> % vertices\n" p vCount
		p = p - 5			-- reduce percentage by 5 points for the next round
	) while (p>5) and (vCount > desiredCount)   -- stop at 5% or when vertcount is below threshold
)

 This could be slow for dense meshes and you could be more sophisticated in how you search for the right percentage (e.g. binary search, i.e. start at 50% then go up or down by 25%, rinse and repeat). This is "left as an exercise for the reader" 🙂

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes
Message 3 of 8

MartinBeh
Advisor
Advisor

OK, so I nerd-sniped myself...

 

Here is the binary search version:

(  -- M. Breidt (22.03.2025) - do a binary search on ProOptimizer percentage until vertex count is reached
	local obj = selection[1]
	local p = 100.0				-- start percentage
	local desiredCount = 200		-- how many vertices should be left?

	-- prepare modifier
	local m = ProOptimizer()
	addModifier obj m
	m.calculate = true
	
	-- helper function to evaluate the result of the current settings
	fn getVertCount = obj.numverts
	
	fn binarySearchParameter param getCurrentValueFn targetValue minValue maxValue tolerance = (
		-- Binary search on parameter
		local low = minValue
		local high = maxValue
		local mid = (low + high) / 2.0
		local iterations = 0 

		while (iterations < 100) and ((high - low) > tolerance) do (
			iterations += 1
			param.value = mid							-- set new value
			local currentValue = getCurrentValueFn()	-- get result of new value
			format "% - Testing parameter value % -> result: %\n" iterations mid currentValue

			if abs(currentValue - targetValue) < tolerance then (
				format "Found parameter value: %\n" currentValue
				return currentValue
			)  else if currentValue < targetValue then (
				low = mid
			) else (
				high = mid
			)
			mid = (low + high) / 2.0		-- new test value
		)
		format "Exact parameter value not found within given tolerance.\n"
		undefined
	)

	format "Trying to get below % vertices:\n" desiredCount
	binarySearchParameter m[1] getVertCount desiredCount 0.1 100 0.1
)
Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes
Message 4 of 8

james_murphieJ25KK
Explorer
Explorer

Thanks for your reply! This definitely helped move in the right direction. The issue I'm running into now however is that the script adjusts the optimization level correctly but I need the final number of faces in the statistics panel to be under 64000. I've attached a screenshot to illustrate this better. Do you think this is possible? From what I understand the pro optimizer modifier only reports back the current vertex number not the statistics before and after? Thanks again for your assistance!

0 Likes
Message 5 of 8

MartinBeh
Advisor
Advisor
Accepted solution

Oh, my bad for not reading carefully. You want the final number of faces not vertices.

 

Luckily this should only need a tiny change:

In my last code, replace

fn getVertCount = obj.numverts

with

fn getVertCount = obj.numfaces

Of course one should eventually also change the function name from "getVertCount" to "getFaceCount" everywhere in the code...

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
Message 6 of 8

james_murphieJ25KK
Explorer
Explorer

Works great! Thank you

0 Likes
Message 7 of 8

james_murphieJ25KK
Explorer
Explorer

I do have one more question if you have time, If I wanted to apply this to a selection of objects in the scene and have the script loop through each object how would I achieve this? Currently if I run the script when there is a selection of objects it applies the pro optimizer modifier but doesn't calculate.  

0 Likes
Message 8 of 8

MartinBeh
Advisor
Advisor

The line

local obj = selection[1]

is what you need to look at. Right now, it always uses the first selection.

 

You can change this to

for obj in selection do (

and then add one more closing parenthesis at the end.

 

But really you want to wrap the poly reduction part into a function that can then be applied to one ore more scene objects.

 

The script I shared above is only a prototype. To make this more robust, one should probably also check whether the current object works with ProOptimizer (e.g. to avoid an error when trying to run it on a helper or a shape object.

Also, you might run into problems if you select multiple instances (clones) of the same mesh.

Martin B   EESignature
→ please 'Like' posts that are helpful; if a post answers your question please click the "Accept Solution" button.
0 Likes