Notifications
Clear all

[Closed] mirror script, optimizations

Hey,

     I wrote a small script to mirror the current face/element selection of an editable poly object. It works, only when the face selection exceeds about 2000 faces, it's getting quite slow. So, I was wondering if anyone has ideas where to optimize this.
     
    For example the center of the selection?..is there a function/variable to retrieve the position of the transformation gizmo? So I don't have to calculate it...
    
   In short what the script does:
   [b]#1[/b] get face Selection & convert to vert selection
   [b]#2[/b] loop through all verts and collect their x, y, z positions
   [b]#3[/b] calc the selection center using the amin/amax for xzy from [b]#2[/b]
   [b]#4[/b] loop through all verts and mirror their pos relative to the selection center, based on the toolmode.axisConstraint
   [b]#5[/b] flip normals if necessary

   (
   	function fnCalcCenter aNPos = fCenter = ((amax aNPos - amin aNPos) / 2 + amin aNPos)
   	
   	if $ != undefined and classOf $ == Editable_Poly do (
		baFaceSel = polyOp.getFaceSelection $
		if baFaceSel.numberset > 0 and subobjectLevel == 4 or subobjectLevel == 5 do (
   
			p3SelCenter = [0,0,0]
   			p3nVPos = [0,0,0]
   			aXPos = #()
   			aYPos = #()
   			aZPos = #()
   			bFlipNormals = false
   			tmAxis = toolmode.axisConstraints
   
   			disableSceneRedraw()
   		
   			$.ConvertSelection #Face #Vertex
   			aVertSel = (polyOp.getVertSelection $ as array)
   			i = 1
   			
   			for nV in aVertSel do (
   				aXPos[i] = (polyOp.getVert $ nV)[1]
   				aYPos[i] = (polyOp.getVert $ nV)[2]
   				aZPos[i] = (polyOp.getVert $ nV)[3]
   				i += 1
   			)
   			
   			p3SelCenter = [(fnCalcCenter aXPos),(fnCalcCenter aYPos),(fnCalcCenter aZPos)]
   			
   			for nV in aVertSel do (
   				p3nVPos = polyOp.getVert $ nV
   				
   				case tmAxis of (
   					#x: (
   						fXAxisOff = (p3SelCenter.x - p3nVPos.x) + p3SelCenter.x
   						p3MirPos = [fXAxisOff, p3nVPos.y, p3nVPos.z]
   						bFlipNormals = true
   					)
   					#y: (
   						fYAxisOff = (p3SelCenter.y - p3nVPos.y) + p3SelCenter.y
   						p3MirPos = [p3nVPos.x, fYAxisOff, p3nVPos.z]
   						bFlipNormals = true
   					)
   					#z: (
   						fZAxisOff = (p3SelCenter.z - p3nVPos.Z) + p3SelCenter.z
   						p3MirPos = [p3nVPos.x, p3nVPos.y, fZAxisOff]
   						bFlipNormals = true
   					)
   					#xy: (
   						fXAxisOff = (p3SelCenter.x - p3nVPos.x) + p3SelCenter.x
   						fYAxisOff = (p3SelCenter.y - p3nVPos.y) + p3SelCenter.y
   						p3MirPos = [fXAxisOff, fYAxisOff, p3nVPos.z]
   					)
   					#yz: (
   						fYAxisOff = (p3SelCenter.y - p3nVPos.y) + p3SelCenter.y
   						fZAxisOff = (p3SelCenter.z - p3nVPos.Z) + p3SelCenter.z
   						p3MirPos = [p3nVPos.x, fYAxisOff, fZAxisOff]
   					)
   					#zx: (
   						fZAxisOff = (p3SelCenter.z - p3nVPos.Z) + p3SelCenter.z
   						fXAxisOff = (p3SelCenter.x - p3nVPos.x) + p3SelCenter.x
   						p3MirPos = [fXAxisOff, p3nVPos.y, fZAxisOff]
   					)
   				)
   
   				polyOp.setVert $ nV p3MirPos
   			)
   			if bFlipNormals do polyOp.flipNormals $ baFaceSel
   		)
   	)
   	enableSceneRedraw()
   ) 
             
2 Replies

Executing with ‘undo-off’ makes scripts run a lot faster but then you might need undo for this tool.

There’s a section in the MaxScript docs about how to speed up scripts and it’s worth a read.

A couple quick things that I can see…

Define the selected object as a variable so that it doesn’t have to constantly be checked (obj = $), same with the polyOp methods (pOp_gv = polyOp.getVert, etc.). That way these things are stored once and called from memory without having to be evaluated every time.