Notifications
Clear all

[Closed] Flatten multiple faces onto a single plane?

I’m trying to figure out the best way to take a series of faces on several different objects, and flatten them all along a single plane. For some reason this has turned out to be much more difficult than I imagined it would.

What I would like to do would just be to draw straight line that averages the center points of each of the faces, and use some combination of that and each of the face’s normals to scale them all to sit exactly on that plane. It seems like it should be fairly easy to do, but I just can’t seem to make it work.

5 Replies

Why not try a sidestep approach. From the faces, figure out the vertexes that make those faces, then move all the vertexes to the same plane, then all the faces will be on that plane. Check out my VertPlacer script if you want to steal some code…

http://www.neilblevins.com/soulburnscripts/soulburnscripts.htm

  • Neil

Thanks Neil, that should help immensely. I’ll look it over

Hm… Sorry, Neil. Either that’s not giving me what I need or I’m not clearly understanding how I’m supposed to use it. It only seems to want to flatten things to world space.

Let me post my most recent attempt and maybe you can see what I’m doing wrong.

This is a test script for using on a group of single-polygon editable polys, and rather than trying to flatten them along a plane, I’m just using a plane object to test the matrix I’m getting (which is not only wrong, but the Z-axis gets bent out of place).


 face_Array = #()
 connect_Array = #()
 cross_Array = #()
 up_Array = #()
 
 fn addUp theVector theArray= 
 (
 	theVector = [0,0,0]
 	for v in theArray do theVector = theVector + v
 	theVector = normalize (theVector / theArray.count)
 )
 
 -- average position
 thePos = [0,0,0]
 for s in selection do thePos = thePos + s.pos
 thePos = thePos / selection.count
 
 -- average face vector (averages the face normals)
 for s in selection do
 (
 	theFace = polyOp.getFaceNormal s 1
 	append face_Array theFace
 )
 addUp faceVector face_Array
 
 -- average connect vector (averages the lines between faces)
 for s = 1 to (selection.count - 1) do
 (
 	theConnect = normalize (selection[s + 1].pos - selection[s].pos)
 	append connect_Array theConnect
 )
 addUp connectVector connect_Array
 
 -- average cross vector
 for s in selection do
 (
 	theCross = normalize (cross connectVector faceVector)
 	append cross_Array theCross
 )
 addUp crossVector cross_Array
 
 -- average up vector
 for s = 1 to selection.count do
 (
 	theUp = normalize (cross cross_Array[s] connectVector)
 	append up_Array theUp
 )
 addUp upVector up_Array
 
 theMatrix = matrix3 crossVector upVector faceVector thePos
 
 thePlane = plane(); thePlane.transform = theMatrix
 
1 Reply
(@artofsoulburn)
Joined: 11 months ago

Posts: 0

Yes, that script aligns things to world space. I was just suggesting using the code as a base, on which you could modify it to flatten the vertexes to any arbitrary plane. I hadn’t done that part

Anyways, glad you’ve got something working now.

  • Neil

Okay, I got it working. (The following always works on face #1 for the selected objects. Getting it to work for other faces shouldn’t be too hard at this point)

avgPos = [0,0,0]
for s in selection do avgPos = avgPos + s.pos
avgPos = avgPos / selection.count

faceNormalArray = #()
for s in selection do
(
	faceNormal = in coordsys s polyOp.getFaceNormal s 1
	append faceNormalArray faceNormal
)
facesVector = [0,0,0]
for s = 1 to selection.count do facesVector = facesVector + faceNormalArray[s]
facesVector = facesVector / selection.count

connectVector = normalize (selection[selection.count].pos - selection[1].pos)

rightVector = normalize (cross facesVector connectVector) 
upVector = normalize (cross rightVector connectVector)
theMatrix = matrix3 rightVector upVector connectVector avgPos

for s in selection do
(
	for v = 1 to s.numVerts do
	(
		thePos = in coordSys theMatrix polyOp.getVert s v
		in coordSys theMatrix polyOp.setVert s v [thePos.x, 0, thePos.z]
	)
)