But for now, here's a script to try and correct ngons. It's got a few problems, I haven't had time to debug. Also you'll notice it's a bit of a monster script and for anyone trying to follow along... good luck, you'll need it!
Important: There are some instances where this script crashes max. I have not fully debugged the cause yet. Use with caution!
USAGE
- Select one or more objects
- run script
* there seems to be some cases where it doesn't completely finish. Run it again if so.
( local CurrentObj local CurrentFace local FirstVert local faceedges = #() local faceedgeverts = #() local faceverts = #() local facevertedges = #() local vertneighbourverts = #() local StructFaceVerts = #() local StructVertConnections = #() fn ConnectAndWalk v1 v2 innerverts = ( --format "ConnectAndWalk: %, %, %\n" v1 v2 innerverts nextv1 = ((vertneighbourverts[v1] - innerverts) as array)[1] nextv2 = ((vertneighbourverts[v2] - innerverts) as array)[1] if nextv1 == v2 or nextv2 == v1 then return true --end of the line, punk! polyop.createedge CurrentObj v1 v2 -- this has become so ridiculously abstract, i guarantee i wont understand this when i look back. OH HEY FUTURE MIKE! -- if the neighbouring verts of the next verts have none in common, we can connect if ((vertneighbourverts[nextv1] * vertneighbourverts[nextv2])).numberset == 0 then (ConnectAndWalk nextv1 nextv2 #{v1,v2}) return true ) struct StructVertConnection ( v1, v2, --FormsTriangle, --FormsQuad, InsideVerts, VertDistance, on create do ( VertDistance = distance (polyop.getvert CurrentObj v1) (polyop.getvert CurrentObj v2) ) ) fn BuildConnectionsFromVert v1 v2 ed = ( NextEdge = ((facevertedges[v2] - facevertedges[v1]) as array)[1] NextVert = ((faceedgeverts[NextEdge] - faceedgeverts[ed]) as array)[1] vertneighbourverts[v1][v2] = true vertneighbourverts[v2][v1] = true if faceverts.count <= 5 then --we only care about tri-making connections if we have a 5-sided (append StructVertConnections (StructVertConnection v1 NextVert InsideVerts:#{v2})) -- FormsTriangle:true FormsQuad:false (these work but arent needed under new system) NextNextEdge = ((facevertedges[NextVert] - facevertedges[v2]) as array)[1] NextNextVert = ((faceedgeverts[NextNextEdge] - faceedgeverts[NextEdge]) as array)[1] --FormsQuad = if faceverts.count <= 5 then false else true append StructVertConnections (StructVertConnection v1 NextNextVert InsideVerts:#{v2, NextVert}) -- FormsTriangle:(not FormsQuad) FormsQuad:FormsQuad (these work but arent needed under new system) if v2 == FirstVert then return true -- end recursion BuildConnectionsFromVert v2 NextVert NextEdge return true ) fn FixFaceNgons obj f = ( faceedges = #() faceedgeverts = #() faceverts = #() facevertedges = #() vertneighbourverts = #() StructFaceVerts = #() StructVertConnections = #() CurrentObj = obj CurrentFace = f faceverts = polyop.getFaceVerts obj f if faceverts.count < 5 then return false facevertsba = faceverts as bitarray faceedges = polyop.getFaceEdges obj f faceedgesba = faceedges as bitarray faceedgeverts = #() facevertedges = #() vertneighbourverts = #() for v in faceverts do facevertedges[v] = ((polyop.getEdgesUsingVert obj v) as bitarray) * faceedgesba for ed in faceedges do faceedgeverts[ed] = ((polyop.getVertsUsingEdge obj ed) as bitarray) * facevertsba for v in faceverts do vertneighbourverts[v] = #{} -- we populate this later StructFaceVerts = #() StructVertConnections = #() firstedgeverts = for v in faceedgeverts[faceedges[1]] collect v FirstVert = firstedgeverts[1] StructVertConnections = #() BuildConnectionsFromVert firstedgeverts[1] firstedgeverts[2] faceedges[1] --for vc in StructVertConnections do (print vc) shortestvc = StructVertConnections[1] for vc = 2 to StructVertConnections.count do ( if StructVertConnections[vc].VertDistance < shortestvc.VertDistance then (shortestvc = StructVertConnections[vc]) ) ConnectAndWalk shortestvc.v1 shortestvc.v2 shortestvc.InsideVerts return false ) fn FixAllNgons obj = ( --disablesceneredraw() polyop.retriangulate obj #{1..(polyop.getnumfaces obj)} f = 0 while 1 == 1 do ( f += 1 if (FixFaceNgons obj f) then f = 0 if f >= (polyop.getnumfaces obj) then exit ) enablesceneredraw() completeredraw() ) fn FixAllConcave obj = ( ) fn FixSelectedObjectsNgons = ( usersel = getcurrentselection() for o in usersel where superclassof o == geometryclass do ( if classof o != editable_poly then ( messagebox (o.name + " is not an editable poly") continue ) FixAllNgons o FixAllConcave o ) ) FixSelectedObjectsNgons() )