Forum Groups
  All forums
    Help & Feedback
      Work in progress
      Finished Art
      Non-Max related

Featured Threads
  inspiration alert!!!
(36 replies)
  Indespensible MaxScripts, Plugins and 3rd Party Tools
(37 replies)
  The allmighty FREE Resources Thread !
(17 replies)
  spam alert!!!
(4886 replies)
  Maxforums member photo gallery index
(114 replies)
  Maxforums Member Tutorials
(89 replies)
  three cheers to maxforums...
(240 replies)
  101 Things you didnt know in Max...
(198 replies)
  A Face tutorial from MDB101 :D
(95 replies) Members Gallery
(516 replies)
(637 replies)
  Dub's Maxscript Tutorial Index
(119 replies)

Maxunderground news unavailable

First page  Go to the previous page   [01]  [02]  Go to the next page  Last page
Surface Analysis
show user profile  erne
hi folks, been a while since I last dropped by.

I need to somehow check a mesh for planarity. It is a Quad mesh, and I need to know if the quad polys are perfectly planar. Do you know of a way to do this?


read 968 times
4/23/2008 7:09:07 AM (last edit: 4/24/2008 4:14:18 AM)
show user profile  maxwin
i'm lost... dumb it down a bit :)

read 960 times
4/23/2008 7:21:09 AM (last edit: 4/23/2008 7:21:09 AM)
show user profile  horizon
You mean to know if each quad is flat, and not broken down the middle edge? I have no idea how to do it automatically :P

read 950 times
4/23/2008 7:31:41 AM (last edit: 4/23/2008 7:31:41 AM)
show user profile  Toen
You could write a script that checks each quad in the model. Something like getting and storing the cross product vector at each vert in the quad relative to it's 2 neighboring verts on each side for the particular quad and then after having collected all of the cross product vectors for the verts in the quad, compare their angles to each other using their dot products with each other and if all of their angles are 0 then the quad is planar.

At least I think that would work.


You could convert the model into an editable mesh, apply a Smooth modifier to it with Auto Smooth checked and threshold set to 0.0 and then visually inspect the model to see if there are any shading differences within a particular quad, that might not be as accurate as a scripted way though.
read 912 times
4/23/2008 11:26:25 AM (last edit: 4/23/2008 11:40:05 AM)
show user profile  Dub.
If you're writing a script, just transform all the polys into the coord space of one of the polys then just loop through the verts and look for any that are not 0 in Z

read 883 times
4/23/2008 2:17:13 PM (last edit: 4/23/2008 2:17:13 PM)
show user profile  Toen
I wrote a script to do this, seems to workout right. It scans through all of the polys of an editable poly object that is currently selected and if it finds any non-coplanar polys, it makes them selected in the Polygon sub-object level. If you copy the below code and past it into a new script window and then hit ctrl-e, it should run it on your poly object. Just make sure you have an editable poly object selected. I put in comments, I hope it makes sense but I was listening to first two seasons of Dr. Who soundtrack. I just used cross products in it instead of cross products/dot product combo i mentioned earlier. This should reveal any poly that is not coplanar regardless if it is 4 side or not.

---Scans an Editable_Poly object for polys that are not coplanar and makes them selected

polyObj=$ -- Poly to be scanned for non-planar
numFaces=polyOp.getNumFaces polyObj; -- number of faces/polys in the polyobject
nonPlanarFaces=#()--will contain the index number of polys that are not coplanar
polyOpGetVertsUsingFace=polyop.getVertsUsingFace -- store function in variable so it only has to be looked up once by max
polyOpGetVert=polyOp.getVert -- store function in variable so it only has to be looked up once by max
for i=1 to numFaces do (--iterate through each poly in the polyobject
faceVerts=(polyOpGetVertsUsingFace polyObj i) as array --gets an array containing the index number of each vert in the poly being checked
numFaceVerts=faceVerts.count -- number of verts in the poly being checked
loopCheck=true -- flag used to exit early out of for loop that compares each verts cross product vector
firstCPVectorFlag=false -- flag used to store the first vert's cross product vector
firstCPVector -- variable that will hold the first vert's cross product vector for each poly/face loop check
for vert in faceVerts while loopCheck do (-- iterate through each vert in the current poly
vertArrayIndex=findItem faceVerts vert -- get the index of the current vert being iterated on
case of ( -- Case check to find the left and right neighboring vertex indexes relative to the current vertex being iterated on in loop
(vertArrayIndex==1) : (--current vertex index is at beginning of vert index array
leftVertArrayIndex=numFaceVerts -- left vertex is at end of the vertex index array
rightVertArrayIndex=vertArrayIndex+1 -- right vertex is +1 index over
(vertArrayIndex==numFaceVerts) : (--current vertex index is at end of the vert index array
leftVertArrayIndex=numFaceVerts-1 -- left vertex is -1 index over
rightVertArrayIndex=1 -- right vertex is at beginning of the vertex index array
default: (--current vertex index is not at the beginning or end of the vertex index array
leftVertArrayIndex=vertArrayIndex-1 -- left vertex is -1 index over
rightVertArrayIndex=vertArrayIndex+1 -- right vertex is +1 index over
--Get vector from the current vertex to it's left neighbor vertex
leftVector=polyOpGetVert polyObj faceVerts[leftVertArrayIndex] - polyOpGetVert polyObj faceVerts[vertArrayIndex]
--Get vector from the current vetex to it's right neighbor vertex
rightVector=polyOpGetVert polyObj faceVerts[rightVertArrayIndex] - polyOpGetVert polyObj faceVerts[vertArrayIndex]
crossVector=cross leftVector rightVector -- Get the resulting cross product vector for the current vertex
if (firstCPVectorFlag==false) then (-- If true then this is first loop into particular poly's vertex checking
firstCPVectorFlag=true -- set flag to true so the following code is only executed once per poly being checked
firstCPVector=crossVector -- store first vert's cross product vector, it will be compared to the vert's cross product vectors
) else ( -- all other loop iterations outside of the first one
--compare the resulting length of cross products between first vert for poly and next vert being checked against
-- If it does not equal 0.0 then that means the two vectors being compared are not parallel and that the resulting face/poly is not coplanar
if ( length (cross firstCPVector crossVector)!=0.0 ) then (
loopCheck=false -- break out of the loop sense the poly/face has been shown to be not parallel so no need to continue checking other vert vectors
append nonPlanarFaces i -- store the current index of the poly/face being checked that failed to be coplanar

)--end for vert
polyop.setFaceSelection polyObj nonPlanarFaces -- set as selected all poly/faces in the poly object that are not coplanar
redrawViews() -- refresh the viewport so that the selected polys will be shown without having to interact with the viewport manually first


read 856 times
4/23/2008 4:56:42 PM (last edit: 4/23/2008 5:18:25 PM)
show user profile  jbrophy
Looks like a solid script. Couldn't you avoid all the vertex needs by doing a normalized


Comparing the face between 2 edges?

Jesse Brophy

Fry Monkey

read 831 times
4/23/2008 6:40:57 PM (last edit: 4/23/2008 6:40:57 PM)
show user profile  Dub.
hah the man has a point!

read 825 times
4/23/2008 6:49:13 PM (last edit: 4/23/2008 6:49:13 PM)
show user profile  Toen
Do you mean to compare the cross product vector created by two edges to that of the polygon normal? Looks like that would work too but I think you would still have to go down to the vertex level in order to get the right vectors to do the cross with to make the check. Am I understanding you right?
read 796 times
4/24/2008 12:44:40 AM (last edit: 4/24/2008 12:44:40 AM)
show user profile  erne
hi folks....

I recently used this forum as an example of a really good site.... Its not particularly flashy or anything, but there is so much going on, and the knowledge to be found... it amazes me...

thats why I've had an accout here for.. i dunno... 10 yrs?

Anyway, many thanks for the script Toen.
However, It does seem to generate som e unexpected results. The outer set of faces on each of these shells IS planar. (it is scripted as a translational surface in the parametric 3d software Generative Components)

I used GC to generate the initial non thickness outer face geometry of these shells. The reason why I use max now is for the ease. It is way easier to use, and quicker. For production issues, it is, however, extremely important to be able to evaluate the planarity of the polys, as they should eventually be cladded with natural stone.

So the curious thing is that the script selects polys that I know to be planar. I would expect it to be the edges and inside after having applied a shell modifier to the GC surface.

Any clues as to why it doesn't seem to work totally?

oops: the image:

read 785 times
4/24/2008 2:32:07 AM (last edit: 4/24/2008 2:34:52 AM)
show user profile  Dub.
It might need a threshold added to account for floating point inaccuracies

change this line:
if ( length (cross firstCPVector crossVector)!=0.0 ) then (

to this: (change the number to suit the accuracy you require)

if ( length (cross firstCPVector crossVector)>0.0001 ) then (

read 775 times
4/24/2008 2:54:24 AM (last edit: 4/24/2008 2:57:14 AM)
show user profile  erne

Hmm then it selects all faces...

read 766 times
4/24/2008 3:13:02 AM (last edit: 4/24/2008 3:13:02 AM)
show user profile  Toen
yeah that must be the problem, except make it < or <= instead of > in that line of code.


if (length (cross firstCPVector crossVector)<=0.003) then (

read 761 times
4/24/2008 3:24:57 AM (last edit: 4/24/2008 3:34:43 AM)
show user profile  erne
for got to adjust the !=, doh

adjusted it to > or < ... it does the same more or less...
I've uploaded the file since it still does weird stuff...could it be something with my geometry?
The outer polygons are flat. the edges, and inner surface are probably not, thats what I need to test.
However, the result of the script puzzles me....

read 747 times
4/24/2008 3:54:22 AM (last edit: 4/24/2008 5:36:17 AM)
show user profile  Toen
Yeah if you are going to use an inequality sign it should be of the type > or >= it's suppose to flag values that aren't at 0.0 or close to it (sorry dub!). That doesn't fix the problem though, checking it out.
read 716 times
4/24/2008 10:55:09 AM (last edit: 4/24/2008 10:55:09 AM)
First page  Go to the previous page   [01]  [02]  Go to the next page  Last page
#Maxforums IRC
Open chat window