[Closed] Break Non Planar Polygons into Triangulated Polygons
It seems like this should be simple, but I’m not finding any good leads on the net… Maybe the terminology I’m using for search is the problem.
I have a function that is always taking geometry and converting to Editable Poly. Before the rest of the script runs, I want to find all non-planar polygons and break the non-planar parts of those polygons into new planar polygons along the same pattern as the triangulation of the poly.
So the question is two part:
-
How to collect just non-planar polygons in an editable poly?
-
How to break the polygon into more polygons that match the triangulation? (It seems like there should be a method for this already, but I cannot find it).
first of all the task is not trivial.
there are two (at least i see two) ways to do it.
#1 (simple)
- convert to editable mesh
- loop through all faces to:
a) find not visible edges
b) check that the edge shared by more then 1 face (you have to check reverse edge)
c) if the edge faces have different normals make the edge visible - convert to editable poly
#2… do want to know more complicated way?
I guess the complicated way would be faster to compute because it would skip the mesh converting etc?
My guess would be to create vectors between poly face verts and see if they intersect.
no… the complicated way is not really faster. it doesn’t need conversion from poly to mesh, and back.
it’s similar to #1:
#2
- snapshortasmesh and use the result mesh to:
- loop through all faces to:
a) find not visible edges
b) check that the edge shared by more then 1 face (you have to check reverse edge)
c) if the edge faces have different normals create new edge for original poly using the mesh edge verts.
I can’t look it up now but it should be fairly easy. I remember that there is a function like isPolyFacePlanar (or similar).
You can, for example, collect all non planar faces in a loop, then detach them, then turn to mesh with all edges visible. Then re-attach the result again.
Hmm, I’m fairly sure I did this some time ago. Maybe there is a function in some maxscript lib on the web. I can check tomorrow.
Denis,
Your solution was what I was thinking already but I wanted to save the overhead of convert to mesh and back to poly. I had hoped there was a better way. The function will almost always be run on collections of hundreds or thousands of objects.
The next question is whether your more complex answer might be faster than the above solution? If it is, I’d love some hints/examples. My main interest is speed.
adding edges to a poly object is very very slow and the slowness is proportional to the number faces in the poly object.
the bottle neck of both methods is getedgesreverseedge function. it’s slow…
Ops! everything is very simple. just use turn_to_poly modifier with requirePlanar option
DOH!.. that was easy! I simply had missed it above… must have blended in my eyes as the signature line.
Denis… you are verifiably… A GOD. You have all answers.
PS. For my needs, the planarThresh to 0.1 worked best.
honestly before i found the simple solution i wrote 5 different functions with various luck…
here is the best one:
fn planarTriangulate node =
(
mesh = converttomesh node
theHold.Begin()
for f in mesh.faces as bitarray do
(
for k=1 to 3 do setEdgeVis mesh f k on
)
converttopoly node
ee = for e in node.edges as bitarray collect
(
ff = polyop.getedgefaces node e
if ff.count >= 2 and (polyop.getfacenormal node ff[1] != polyop.getfacenormal node ff[2]) then (polyop.getEdgeVerts node e) else dontcollect
)
-- node.selectededges = ee as bitarray
if theHold.Holding() do theHold.Cancel()
for v in ee do polyop.createedge node v[1] v[2]
update p
)
works pretty fast.
you could try selecting all the objects you need to adjust add an editmesh mod…
select all the edges
set auto edge threshold to 0.1
press auto edge
convert to poly
also you may run into other issues regarding smoothing groups.
Denis, the function listed above has errors… perhaps you pasted a different version from your final?
Anyway, since the above turn_to_poly modifier fixed the problem, now I’m trying to adapt your function to simply return true or false if a node has non-planar polygons. But I seem to be failing. For the moment in this function, I want to detect any object so convert only to mesh as a copy. But the results are inconsistent.
This is how I adapted it. It seems to be correct a lot… but some objects it fails on.
fn hasNonPlanarPolygon node =
(
local hasNonPlanarPolygon = false
if superClassOf node == GeometryClass then (
local mesh = copy node
converttomesh mesh
for e in mesh.faces as bitarray while hasNonPlanarPolygon == false do (
ff = (meshop.getPolysUsingFace mesh e ignoreVisEdges:true) as array
if ff.count >= 2 and (getfacenormal mesh ff[1] != getfacenormal mesh ff[2]) then (
hasNonPlanarPolygon = true
)
)
delete mesh
)
return hasNonPlanarPolygon
)
c’mon! errors! there is only one small bug (like this ¤). to fix it just change p at the end of function to node
Yeah I know I only mentioned so you could edit post if you felt like it