Help with turning reapable viewport and editpoly operations into automatic script.

Help with turning reapable viewport and editpoly operations into automatic script.

robert_butler
Participant Participant
481 Views
3 Replies
Message 1 of 4

Help with turning reapable viewport and editpoly operations into automatic script.

robert_butler
Participant
Participant

Hi, I'm a newbie to max scripting. I can sort of understand code enough to read what an already written script is doing, but writing one from scratch is currently beyond me.

 

I'm dealing with a model set of 1000s of low poly objects, each with triangulated and detached faces.

 

I have a series of operations I can do per object in the viewport that cleans the models up quickly and consistantly, but it's still not viable to do it one at a time. I'd like to compile a script to automate the proccess instead.

 

I've tried using the macro recorder to get a list of scripts for what I'm doing, but things like "invert selection" and "select all" are recorded as "set selection, edges: 0001, 0002, 0003, etc....".

 

Basically the operation I want to automate is - for an array of selected objects, one object at a time:

(All objects are Editable Poly)

1. Weld all vertices at 0.001 Weld Threshold. (My scene is in meters and units are set to generic.)

2. Run the following script to select edges by angle (credit to Bobo from CGtalk forums):

macroScript SelEdgesByAngle
category:"# Scripts"
buttontext:"Edges By Angle"
tooltip:"Select Edges By Angle"
(
local theThreshold = 5
local include_open_edges = false	
local auto_preview_selection = true
fn filter_function =
(
theObj = modPanel.getCurrentObject()
subObjectLevel == 2 and selection.count == 1 and (classof theObj == Editable_Poly or (classof theObj == Edit_Poly and theObj.enabled and theObj.enabledInViews))
)
on isEnabled return filter_function()
on isVisible return filter_function()

fn perform_selection =
(
selEdges = #{}
theObj = $

eCount = polyOp.getNumEdges theObj
for e = 1 to eCount do
(
theFaces = (polyOp.getEdgeFaces theObj e) as array
if theFaces.count == 2 then
(
theAngle = acos(dot (polyOp.getFaceNormal theObj theFaces[1]) (polyOp.getFaceNormal theObj theFaces[2])) 
if theAngle >= theThreshold do selEdges[e] = true
)	
else 
if include_open_edges do selEdges[e] = true
)
case classof (modPanel.getCurrentObject()) of
(
Editable_Poly: polyOp.setEdgeSelection theObj selEdges 
Edit_Poly: (modPanel.getCurrentObject()).SetSelection #Edge &selEdges 
)	
redrawViews()	
)

on execute do perform_selection()

on altExecute theType do
(
rollout SelEdgesByAngle_Rollout "Select Edges By Angle"
(
checkbox include_open "Include Open Edges" checked:include_open_edges
spinner threshold_value "Angle Threshold" range:[0,180,theThreshold] type:#float fieldwidth:60
checkbutton preview_selection "Preview" width:85 across:2 align:#left checked:auto_preview_selection
button select_now "Update" width:85 align:#right
on threshold_value changed val do 
(
theThreshold = val
if preview_selection.checked and filter_function() do perform_selection()
)	
on include_open changed state do 
(
include_open_edges = state
if filter_function() do perform_selection()
)	
on preview_selection changed state do auto_preview_selection = state
on select_now pressed do if filter_function() do perform_selection()
)
createDialog SelEdgesByAngle_Rollout 200 70 
)
)

3. Invert the selected edges.

4. Remove the selected edges (same behaviour as pressing the backspace key in viewport).

5. Repeat for all objects in selection.

 

This essentially re-attaches the detatched faces and removes the triangulated edges. I doesn't create perfect quads in all cases, but I don't need that anyway.

 

Any help on this would be very much appreciated!

0 Likes
482 Views
3 Replies
Replies (3)
Message 2 of 4

denisT.MaxDoctor
Advisor
Advisor

 

 

macroScript RemoveFlatPolyEdges
	category:"with denisT"
	buttontext:"DEL FLAT EDGES"
	tooltip:"Remove Flat Poly Edges"
	autoUndoEnabled:off
(
	fn getFlatEdges poly angle:10 select:on = 
	(
		edges = #{}
		for edge = 1 to poly.GetNumEdges() do
		(
			ff = polyop.getEdgeFaces poly edge
			if ff.count == 2 do
			(
				n1 = polyop.getFaceNormal poly ff[1]
				n2 = polyop.getFaceNormal poly ff[2]
				if acos (dot n1 n2) < angle do append edges edge
			)			
		)
		if select do poly.selectededges = edges
		edges
	)

	mapped fn removeFlatEdges poly angle:4 = if iskindof poly Editable_Poly do
	(
		getFlatEdges poly angle:angle
		poly.Remove selLevel:#edge
	)
	
	on isEnabled do 
	(
		for node in selection where iskindof node Editable_Poly do return true
		false
	)
	on execute do undo "Remove Flat Edges" on
	(
		ang = if keyboard.shiftpressed then 2 else if keyboard.controlpressed then 10 else 5
		removeFlatEdges selection angle:ang
	)
)



/*
---------------- EXAMPLE ----------------

delete objects
gc()
-- 0:
bx = box pos:[0,0,0] height:30 wirecolor:green
cy = cylinder sides:12 smooth:off pos:[0,0,30] height:20 radius:10 wirecolor:yellow
sp = sphere segments:8 smooth:off pos:[0,0,60] radius:10 wirecolor:red

nodes = #(bx, cy, sp)
converttomesh nodes

-- 1:
mapped fn setMeshAllEdgesVisible mesh = 
(
	for face = 1 to mesh.numfaces do 
		for edge = 1 to 3 do setEdgeVis mesh face edge on
	update mesh
)
setMeshAllEdgesVisible nodes 

-- 2 :
converttopoly nodes

-- 3:
removeFlattenEdges nodes angle:8

*/

 

 

I hope you know how to make macro-button...

 

This macro removes "flat" poly edges by a specified angle (which you can change in the code).
By default, the angle must be less than 5 degrees.

Press button with SHIFT make angle threshold 2

Press button with CTRL make angle threshold 10

 

 

 

 

 

0 Likes
Message 3 of 4

denisT.MaxDoctor
Advisor
Advisor

here is how to weld all polys by threshold:

 

mapped fn weldPolyVertecies poly threshold:0.001 = if iskindof poly Editable_Poly do
(
	_old = poly.weldThreshold 
	poly.weldThreshold = threshold
	polyop.weldVertsByThreshold poly #all
	poly.weldThreshold = _old
	update poly
)
weldPolyVertecies selection threshold:0.001
0 Likes
Message 4 of 4

robert_butler
Participant
Participant

Thanks a lot Denis, I'll see how I go getting this to work!

 

It's a good chance to start learning max scripting a bit more.

0 Likes