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()
)
