Improved make planar for Edit poly


#1

I was working on a script to flatten all faces in a few iterations.
Let’s say you have a skewed cube and you want all the sides to become flat with a single click (just a simplified example).
Scripts like that already exist for editable poly and editable mesh, but I want all my scripts to work on edit poly.

However, when using the buttonOp #MakePlanar command I noticed that I got a different result from editable poly and editable mesh, which work as expected. I zoomed in and saw that it was screwing around with already flat faces and making a mess of the whole mesh. Even when applying it to single faces it was messing up. I compared it to scaling the face locally, which worked as expected.

So I had to ditch using the built-in #MakePlanar function and decided to scale all faces to z 0 locally instead.
Easier said than done, but after messing around for a bit, I have something that I think should work, but doesn’t. After running the script my test cube gets very distorted, and when I move any part of the mesh, the last face in the loop pops to a different location, like the mesh hadn’t updated visually.

Can anyone see what is wrong here?
Could there be an issue with the mesh not updating between the loops or something?

Please try it yourself on a distorted test cube and see if you get the same results as me.
While testing I’m just using a base object, with one edit poly on top, hence “modifiers[1]”.

I would appreciate any help.

for i=1 to (getNumFaces $) do (
$.modifiers[1].setSelection 4 #{}
$.modifiers[1].Select 4 #{i}
fNorm=$.modifiers[1].GetFaceNormal i
fCentLoc=$.modifiers[1].GetFaceCenter i
MatrfNorm=(matrixFromNormal fNorm)
fCent=$.pos+fCentLoc
MatrfNorm[4]=fCent
$.modifiers[#Edit_Poly].ScaleSelection [1,1,0] axis:MatrfNorm
)


#2

I made a script for that a while ago (works on both Editable Poly and the Edit Poly modifier): https://www.youtube.com/watch?v=QeTOYf3GKu8


#3

Yes, I’ve come across that video when looking for a solution.
I would be grateful for any help making the above code work, so that I can make my own tool that I can customize however I like, and continue to build upon.

Thanks


#4

Alright, here’s a cleaned up version of your code:

theObj = (selection as array)[1]
theMod = modpanel.getCurrentObject()
theClass = classOf theMod
if theClass == Edit_Poly do (

    --pre-initialize any function that uses dot notation (optimization / can significantly improve performance)
    gfn = theMod.GetFaceNormal
    gfc = theMod.GetFaceCenter
    doSel = EditPolyMod.setSelection
    setSel = theMod.setSelection
    scaSel = theMod.ScaleSelection
    theObjPos = theObj.pos
    theObjRotInv = inverse theObj.rotation
    
    totalFaces = theMod.GetNumFaces node:theObj
    for i=1 to totalFaces do (
        
        --This method of selecting faces will work no matter what subobject level you're in
        setSel #Face #{} node:theObj
        facesToSel = #{i}
        facesToSel.count = totalFaces
        doSel theMod #Face facesToSel node:theObj
        
        fNorm           = ((gfn i node:theObj) * theObjRotInv)
        fCentLoc        = gfc i node:theObj
        MatrfNorm       = matrixFromNormal fNorm
        MatrfNorm[4]    = theObjPos
        
        scaSel [1,1,0] axis:MatrfNorm
    )
    theMod.commit() --apply the changes to the edit poly modifier
    completeRedraw() --update viewport
)

Note that although most of this will work fine on instanced edit poly modifiers, the scale function itself doesn’t let you specify the object you want it to run on. The correct way to do this would be to calculate the final positions yourself instead of relying on Maxs scale function, this would also give you more control over the final direction of the flattened surface. But as long as you’re not running this on instances it should be ok.


#5

Thanks, man, that’s very kind of you.
I’ll make do without calculating the positions myself, because I don’t know how, yet.
I guess I’ll have to learn how to work with transform matrices :grimacing: