Deleting internal faces in maya

I’ve been looking around the web for a tool to delete internal faces in a Maya scene file but have had little luck. Most suggestions people have offered are to select outer faces, invert selection, and delete, or to use boolean tools. Being that we’re working with a number of different objects with a large amount of polygons, I’d like our solution to be more robust and programmatic. I was thinking about Maya’s native tools and how to determine whether or not a face is internal, and remembered that when creating an AO map, certain parts of the map will bake to black if an area is completely internal. If, for example, 98% of the surface area of a specific UV face’s associated AO map is black, that face would then be safe to delete. However, I’m stumped on a way to compare the uv space for a given face and the associated AO map. Any thoughts on how this might be done? Thoughts on other ways this could be done?

Cheers!

internal = not on geometry borders? Or facing into the center of a closed object?

I believe the former - faces that are within an external border of geometry. Though there is not single mesh that encompasses the “outside”, as it’s a series of separate individual meshes (which could be combined if it made the process easier).

This will get you the internal faces of an object in the geometry sense:


import maya.cmds as cmds
def internal_faces(*obj):
    sel = cmds.ls(sl=True) or []
    if len(obj[0]):
        try:
            cmds.select( *obj) 
            cmds.polySelectConstraint ( m=3, type=8, where=2, dis=True ) #winnow down to internal faces
            cmds.polySelectConstraint ( type=8,  dis=True ) # reset select constraint
            return cmds.ls(sl=True)
        finally:
            cmds.select(*sel) #restor selection

However you’ll probably find that the results always do what you want… There are many shapes which will become non-triangulable if you delete their innars, and fixing that is a non-trivial problem.

What’s the application?

I tried this method out and it didn’t seem to do what I expected.

Here is the application:

A user creates a rock and imports that rock into the scene 100 times and repositions each to create a large rock pile. We’d like to look at each object and determine if any of the other objects in the scene have faces COMPLETELY within the first object. If an object has another objects face(s) within its external border, we would then delete that face(s) and move onto the next object, continuing the process. This would delete all faces in the scene that are fully enclosed by geometry, and thus delete all faces that would never seen by the end viewer. Does this help?

Ah, so you want occluded geometry. That snipped just grabs faces which are not connected to an open edge.

That’s a trickier problem, since it means you have to test potentially every face against every other. It’s also not really soluble at cases containing open objects. Depending on the geometric complexity of the scene (and the possiblity of multiple object nesting) it could be a significant amount of work.

Booleans really is the closest thing to a native tool for this, and unfortunately the famous problems and limitations there are the same ones you’ll face. You could basically try finding possibly intersecting objects with a simple bounding sphere check and maybe an octree to speed up searching and matching. You could try something like this:

  1. find all the pairs of potentially intersecting objects. For each pair:
  2. index the verts by spatial position so you can get object1.vtx[1] from [1.0,2.0,3.0]
  3. do a boolean intersection of the pair, collect it’s vert positions, and then undo it
  4. use your index to find the occluded verts in the original objects
  5. use polyListComponentConversion to turn those verts into faces-that-include-those-verts
  6. add those faces to your list of bad faces
  7. on to the next pair…

at the end, delete the whole list in one shot (don’t change to topology while you’re still checking, in case you have multiple overlaps)

Conceptually I think that works. It’ll be dog slow in Python but this is a non-trivial problem

Probably much more complex but more reliable, something like a pixar style cloud map of the scene to see occluded geo irrespective of camera view or an AO.

This might be easy in something like Houdini actually and you could visualize it quite easily too.

I believe if I read this thread correctly it would look something like this in Houdini.

occluded.zip (9.68 KB)

I don’t know about in maya, but in Max you can use baked lighting to do this. You’d bake the lighting to vertex colours, then you can select verts based on colour with a tolerance. Choose black. Convert to polys (or elements probably in this case so you select the whole of each rock) and delete.

If you can replicate that you might get somewhere.

I’m pretty sure you can do something similar in Maya. Bake AO to the vertices, select vertices that have black vertex color, convert to faces, and delete.

Thanks for the responses everyone. I currently don’t have access to Houdini, so I’m not able to open the file. Could you give an overview of what’s happening? In regards to baking lighting/AO to vertices, I considered this yesterday, and although it’s a good solution it doesn’t get me all the way there. Here’s why:

You could have a single polygonal plane that has all of its vertices occluded by other geometry, but has a portion of the face still viewable (we often run into this scenario). If we bake the AO to the vertices of this face, we’d find them all black, and delete a face that is still partially seen.

It seems like this is a good place to start, but I’d need to find a way to quickly sample other other points within the area of the polygon. Is there a another way to do this so that I can sample more than the baked color of vertices of a given face? Is there a way I can easily discretize (without adding more vertices, even temporarily) the polygon so I can perform a color check on certain points within the polygon?

The file will open in the free learning edition if you want to play with it.

But it basically takes the “rock” geometry converts it to a signed distance field which is then used to create a group of points on the other object that are inside the “rock”. Then it adds an attribute to the points which gets promoted to faces taking the minimum value of the points, meaning that only faces where every point is inside the “rock” get the attribute, and then I just delete those faces. Because it is Houdini it all remains fully procedural even with changes or animation in the geometry (I put an expression on the offset of noise on one of the objects to show this).

You could try creating a giant, authalic, non-overlapping UV map for the whole scene (like one of those Zbrush triangle maps) and baking the AO into that. Then for each UV triangle you grab all the pixels that belong to the triangle and use the histogram of the pixels to accept or reject the face.

The sampling would require taking the UV bounding box of the triangle, getting all of those pixels,
then walking them scanline-style to see if each texel is actually inside the triangle or not… You’re probably OK to ignore partial texels, unless you have so much geo that each tri has only a handful of pixels to start with (otherwise, you have to weight the pixel samples to handle partially included pixels).

If you’re doing this in python it will be pretty sloooow but it would do what you want.

Is this level of detail completely necessary? If these really are all instances of the same set of rocks, it might be sufficiently performant just to hardware instance these guys and thrown them at the GPU, especially if it’s a deferred renderer. Of course, complex collision or physics info wont scale the same way so if that’s the bottlneck you’re stuck.

1 Like