Noob question - trying to delete all faces in -x

504 views
Skip to first unread message

Aren Voorhees

unread,
Jan 27, 2014, 1:13:31 PM1/27/14
to python_in...@googlegroups.com
Hey all,

I am trying to create a tool for modeling that will delete all faces that are located in negative x (as a modeler, I've always wanted something like this).  I've got most of it working - I create a list of the faces, then loop through them, determining their position using the positions of their verts.  It's the last line, or few lines where I'm a bit lost.  I'm appending all faces that come back negative into a list, then trying to delete that list.  Clearly, I'm doing something wrong there.

If you notice anything else that could be done better, feel free to let me know!  

If anyone can help out a lost beginner, I'd be extremely thankful!

import maya.cmds as cmds



#Define object name


curSel = (cmds.ls (sl=True)[0])



numOfFaces = len(cmds.getAttr(curSel + ".f[:]"))


for i in xrange (0,numOfFaces):


    cmds.select(curSel + ".f[%d]" %i, add=1)



#Create list (array) of faces in current object


faceIndexList = cmds.ls(sl=True,fl=True)


   


#Loop through the list of faces from above


for i in faceIndexList:


   


    #Selects the current face


    cmds.select (i)


   


    #Converts selection to verts (tv == toVerts)


    faceToVerts = cmds.polyListComponentConversion (tv=1)


    cmds.select (faceToVerts)


   


    #Stores the selected verts into a variable (fl == Flatten, which lists out things individually)


    vertIndexList = (cmds.ls (sl=True,fl=True))


   


    #Creating empty position variables to later store the vectors of the verts in


    posX = 0


    posY = 0


    posZ = 0


   


    #Loops through verts in vertIndexList


    for j in vertIndexList:


       


        cmds.select (j)


       


        #Sets the total number of selected verts (would be 4 in most cases)


        totalVertNum = len(vertIndexList)


       


        #Gets the vector location of each vert


        vertPos = cmds.xform(query=True, translation=True)


       


        #Supposed add the X value of the selected vert to the value from the previous itteration (starts at 0)


        posX += vertPos[0]


        #Supposed add the Y value of the selected vert to the value from the previous itteration (starts at 0)        


        posY += vertPos[1]


        #Supposed add the Z value of the selected vert to the value from the previous itteration (starts at 0)        


        posZ += vertPos[2]


       


        #Finds the center of the face by creating a vector


        faceCenter = (posX/totalVertNum), (posY/totalVertNum), (posZ/totalVertNum)


   


    #Creates empty list to store negative faces in


    negFaces = []


       


    #If the faceCenterer variable is negative


    if faceCenter[0] < 0:


       


        #Appending all the negative x faces into negFaces


        negFaces.append (i)


       


#I thought this would delete all faces that had been appended into negFaces, but clearly I thought wrong!


for i in negFaces:


    cmds.delete (i)


   


   







Pedro Bellini

unread,
Jan 27, 2014, 9:51:50 PM1/27/14
to python_in...@googlegroups.com
Hi Aren, if I understood right, what you want to do is:
from your object, delete all the faces that have negative X position in relation to the world?

if so, i believe you are doing a bit more work then necessary. This code below is working and it will delete faces on the negative X side of the world
also, normally you don't want to select things with the command line unless you absolutely need to.

Will over comment it just in case...

##============================
import maya.cmds as cmds

# get the selection of the object - you can do some error checking, if not polygon or if component selection...
sel = cmds.ls(sl=1)
#    get the amount of faces
faceCount = cmds.polyEvaluate(sel[0], face=1)
#    array variable to hold negative faces later on
negativeFaces = []
#    loop for each face...
for i in range(faceCount):
    #    check if the X position of that face is negative with xform command, note that [0] is the X value [1] for y, [2] for z
    if cmds.xform(sel[0]+'.f[%d]'%i, q=1, ws=1, t=1)[0] < 0:
        #    if so add to list
        negativeFaces.append(sel[0]+'.f[%d]'%i) # the empty list will hold all the faces in the negative X side after the loop is done
#    delete all faces in negative side
cmds.delete(negativeFaces)
#    clean the history
cmds.delete(sel[0], ch=1)
##=====================================================

hope this helps.
cheers.

Justin Israel

unread,
Jan 27, 2014, 10:09:42 PM1/27/14
to python_in...@googlegroups.com
Nice work Pedro. And just to nitpick a little on it, I might suggest a few tweaks:

##===
sel = cmds.ls(sl=1)

# save this so we don't have to constantly
# index into the array
firstItem = sel[0]

faceCount = cmds.polyEvaluate(firstItem, face=1)

negativeFaces = []

# xrange instead of range in case faceCount is large
for i in xrange(faceCount):
    # just format the attr once
    attr = firstItem + '.f[%d]' % i
    if cmds.xform(attr, q=1, ws=1, t=1)[0] < 0:
        negativeFaces.append(attr) 

cmds.delete(negativeFaces)
cmds.delete(firstItem, ch=1)
##===



--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/1cdd5715-cc8a-4795-aa3e-405ed50eb407%40googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

Pedro Bellini

unread,
Jan 27, 2014, 10:39:15 PM1/27/14
to python_in...@googlegroups.com
Hi Justin, great suggestions.

also, if wanted to separate already the first element, then we can just use the one liner
obj = cmds.ls(sl=1)[0] #like Aren has on the original code

xrange indeed should be used over range since its more efficient while dealing with large amounts. I was testing in a cube with a couple of divisions =\
attr cleanup also looks better

btw, critiques are always welcome.
cheers

Aren Voorhees

unread,
Jan 28, 2014, 11:38:31 AM1/28/14
to python_in...@googlegroups.com
Pedro, Justin - Thank you both so much for your replies.  This is definitely a lot simpler than what I was doing, and I learned a lot from what you both did.  

However, I did have some problems in certain cases with the script - When used on a cube or a plane, it worked as expected.  BUT, when I tried it on a sphere, and then several more complicated character models, it did not give me the correct results.

For example, try running the script on a completely default polySphere .  Unless I am doing something wrong, I do not believe it works quite as expected, as it is deleting some faces it should not, and leaving some that should be deleted.  I am wondering if it because of the xform command?  It seems like the xform of each face is located not in the center, but in the corner.  Therefore (at least in the sphere example) some of the faces that are actually in negative x, come back with an xform of 0.  I'm going to try to do a bit more experimenting on this when I have a chance, but if either of you have any additional thoughts, I'd love to hear them!

Thanks again!
Aren    

aevar.gu...@gmail.com

unread,
Jan 28, 2014, 11:39:21 AM1/28/14
to python_in...@googlegroups.com
Please correct me if I´m wrong but isn´t Edit>Delete by type>backface polygons a default option in Maya?

  Don’t have the full version of Maya to confirm, I may have had a plugin doing this in the past but check it please.  If there are issues with it ( like the faces you want to delete are not in the same axis as your camera  ) then I’d assume the approach would be a simple script along the lines of;

01 - create temp camera in desired axis
02 - select everything with backface culling turned off ( which ignores anything not in sight )
03 - delete polygons
04 - delete temp camera

  Hope this helps, the script does sound a bit overcomplicated for the intent since it’s so super easy to do this in the workspace manually…..

Justin Israel

unread,
Jan 28, 2014, 12:49:36 PM1/28/14
to python_in...@googlegroups.com

Do you want to know if the center is positive X or if any part of the face is positive X?

If you just want to know if a face crosses or is in negative x then you could get the boundingBox with polyEvaluate, and check if the minX is negative.
If you want the center, the Maya API can tell you it (is there a commands equiv?)
http://mayastation.typepad.com/files/getfacecenters-1.py

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Aren Voorhees

unread,
Jan 28, 2014, 3:33:37 PM1/28/14
to python_in...@googlegroups.com
Hey Justin, I gave exactWorldBoundingBox a try and it is working so far on all my tests, thanks!  Here is what I came up with:

import maya.cmds as cmds

#Get current selection

curSel=cmds.ls(sl=1)[0]

#Create list of all faces in object

faceIndex=cmds.polyEvaluate(curSel,face=1)

#Empty list

negativeFaces=[]

#loop through faces

for i in xrange(faceIndex):

     curFace = curSel + '.f[%d]' % i

     #If the exactWorldBoundingBox is negative in X append that face to the empty list

     if cmds.exactWorldBoundingBox (curSel + ".f [%d]" %i)[0] < 0 :

          negativeFaces.append(curFace)

#Delete the faces that were put into the empty list

cmds.delete(negativeFaces)

cmds.delete(curSel, ch=1)


One thing I noticed while working on this (which gave me some serious confusion) is that when you create a default sphere, some of the edges/verts that you would think are exactly in the center of the world, actually aren't.  So when testing this sort of thing on a sphere, I'd recommend snapping all the center verts to the center of the world first, to avoid getting super annoyed, like me ;)


Ævar, that sounds like that might be a good way of doing this too - I'll definitely give it a try, thanks!

Marcus Ottosson

unread,
Jan 28, 2014, 4:26:39 PM1/28/14
to python_in...@googlegroups.com
If you're comfortable using nodes to achieve your goal, then you might be interested in polyCut.

Here's an example as in maya ascii format; either run it as mel, or save it to polycut.ma or such.

requires maya "2014";


createNode transform
-n "mirrorCutPlane1";
 setAttr
".r" -type "double3" 0 90 0 ;
 setAttr
".smd" 4;
createNode sketchPlane
-n "mirrorCutPlane1Shape" -p "mirrorCutPlane1";
 setAttr
-k off ".v";
createNode transform
-n "polySurface1";
createNode mesh
-n "polySurfaceShape1" -p "polySurface1";
 setAttr
-k off ".v";
 setAttr
-s 2 ".iog[0].og";
 setAttr
".vir" yes;
 setAttr
".vif" yes;
 setAttr
".uvst[0].uvsn" -type "string" "map1";
 setAttr
".cuvs" -type "string" "map1";
 setAttr
".dcc" -type "string" "Ambient+Diffuse";
 setAttr
".covm[0]"  0 1 1;
 setAttr
".cdvm[0]"  0 1 1;
 setAttr
".vbc" no;
createNode polySphere
-n "polySphere1";
createNode polyCut
-n "polyCut1";
 setAttr
".uopa" yes;
 setAttr
".ics" -type "componentList" 1 "f[*]";
 setAttr
".ix" -type "matrix" 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1;
 setAttr
".ws" yes;
 setAttr
".mp" -type "matrix" 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1;
 setAttr
".ps" -type "double2" 2.0000002384185791 2 ;
 setAttr
".df" yes;
connectAttr
"polyCut1.out" "polySurfaceShape1.i";
connectAttr
"polySphere1.out" "polyCut1.ip";
connectAttr
"mirrorCutPlane1.t" "polyCut1.pc";
connectAttr
"mirrorCutPlane1.r" "polyCut1.ro";

Aren Voorhees

unread,
Jan 29, 2014, 9:08:00 PM1/29/14
to python_in...@googlegroups.com
Hey Marcus, I gave this a try too, and it seems to be working - I never thought of doing it like this!  I am a bit embarrassed to admit, I also found a way this morning of doing this in Maya with no scripting at all (Mesh-->Mirror Cut).  BUT the important thing is I learned a lot working on the script and hearing other suggestions that people threw out there.  

Thanks again to everyone for their input/ideas!

Marcus Ottosson

unread,
Jan 30, 2014, 2:07:45 PM1/30/14
to python_in...@googlegroups.com
Glad you got it working.

Mirror Cut is also using the polyCut node, have a look in the Hypershade if you're curious to see how it differs.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.



--
Marcus Ottosson
konstr...@gmail.com

Reply all
Reply to author
Forward
0 new messages