Notifications
Clear all

[Closed] Delete Selected Objects that have no Faces

Hi everyone,

I’am new to maxscript and I need a function that deletes a mesh that have no faces.
During merge faces and clone I got hunderets of meshes that have no faces (empty).
And while exporting I got a error messages for each meshes without a face.

Is someone willing to help out with a small script that deletes a mesh that have no faces?
At last it would be very great if the function checks for selected meshes.

Thanks a lot!
Cheers,
David

9 Replies

I only had a spare 5 minutes to test this on a selection of editpoly objects, so this may have bugs:


  
  selectionArr = selection as array -- convert the selection to an array
  
 for i in selectionArr do -- for each object in the array
 (
 	--check the number of faces and if they equal zero(0), delete the object.
 	if polyop.getNumFaces i == 0 then delete i
 
 )
  
  

If you’re running this on editable mesh objects, not edit poly, then replace the polyop with meshop.

Thanks, this works great on ediableMesh and editablePoly.

Unfortunately a lot of the Mesh/Polys are inside groups then it does not work.
I get the following error:

#($Editable_Mesh:N_ZwergNaseLamp26...()
  -- Error occurred in i loop; filename: C:\3dsmax8\Scripts\DelEmptyMeshes.ms; position: 245
  --  Frame:
  --   i: $ZwergNase26
  -- Runtime error: Mesh operation on non-mesh: Dummy
  

Seems to be a group is a dummy.
Do you think there is any chance to handle the routine on meshes/polys in groups too?

For sure, it would be possible to ungroup all, but then it become horrable to edit the existing stuff.

Thanks

I’ll have a look into it tomorrow if someone doesn’t get there before me.

Okay, try this:


 
 
 selectionArr = selection as array
 
 for i in selectionArr do
 (
 	if classof i == Dummy then setGroupOpen i true
 )
 
 
 for i in selectionArr do
 (
 	if classof i != Dummy then
 	(
 		if polyop.getNumFaces i == 0 then delete i
 	)
 )
 
 
 

Technically, it shouldn’t work, as I don’t reassign the now open nodes to the selection array, but it seems to work anyway! Go figure. :shrug:

Yes thanks!

 I recognice the problem. 
 It become very complex to save all obects they are included in an open Dummy and regroup them back at the end. Then you have to search recursive through all objects.
 
 The solution require a native command that deletes objects without faces at a low level. And this one does not exist I think.
 
 Okay a question:
 
 If we found a Dummy, would it be possible to recognice all the objects are inside of the Dummy=i ?

Perhaps a stupid solution.


     for i in selectionArr do
     (
     	 if classof i == Dummy then 
     	 ( 
     		setGroupOpen i true
     		DummyArr = i as array
     				
     		for n in DummyArr do
     		 (
     			if classof n != Dummy then
     			 (
     				  if polyop.getNumFaces n == 0 then delete n
     			 )
     		 )
     		 
     		setGroupClose i true
     		)
      )
     

This is a suggesetion only… I have no idea what happend to the data structures and what definetely inside of an ‘i’.

Would that work ?

The getPolygonCount function returns an array #(number of faces, number of vertices) for any geometric object (mesh/poly/editable spline/etc). I can’t verify this right now, but something along these lines should work:

delete (for obj in Geometry where obj.isSelected and (getPolygonCount obj)[1] == 0 collect obj)

Martijn

Thanks… but I do not come close to your code example.
(As I wrote in the first post, I’m totaly new to max script)

  • Did you consider that meshes are inside of groups?
  • Did I have to exchange you code line anywhere within the other code examples?
1 Reply
(@magicm)
Joined: 11 months ago

Posts: 0

The for obj in Geometry loop (see bottom of this post) only iterates through geometric objects, so groups are automatically skipped. See the ObjectSet Values topic in the online reference for more info about this.

MAXScript really makes no difference whether an object is inside a (closed) group or not. Consider the following example:

Create two boxes and group them together. While keeping the new group selected, execute the following in the Listener:

for obj in selection do print obj
$Box:Box02 @ [3.382957,19.848801,0.000000]
$Box:Box01 @ [4.139214,41.288383,0.000000]
$Dummy:Group01 @ [3.676224,31.021759,8.415952]

So even while the group is closed, its contents are directly visible to MAXScript.

No this line of code should do what you want. Here’s a more readable version of my script:

(

-- create an array to store all empty objects
local ObjectsToDelete = #()

-- iterate through all Geometry objects
for obj in Geometry do
(
	-- check if the object is currently selected
	if obj.isSelected then
	(
		-- check if the object has zero faces
		if (getPolygonCount obj)[1] == 0 then
		(
			-- add the object to the ObjectsToDelete array
			append ObjectsToDelete obj
		)
	)
)

-- delete all objects that have been collected in the above loop
delete ObjectsToDelete

)

And the short version I posted yesterday:

delete (for obj in Geometry where obj.isSelected and (getPolygonCount obj)[1] == 0 collect obj)

Hope this helps,
Martijn

Thanks, works perfect!
And thanks to erilaz for his kind help!

My last question is, would it be possible to access and set the global x/y/z vertex positions of each object in obj. ?

I want to snap all selected vertexes to a selfdefined x/y/z position to correct boolean or snap errors.
(eg. x=0.01 y=0.02 z=0.1 meter)

What I thought about is a lite modificated version:

for obj in Geometry do
  (
  	if obj.isSelected then
  	(
  		for v = 1 to getNumVerts obj do  
  		(
  			vert = getVert obj v  
  			vert.x = abc -- result of any function
  			vert.y = abc -- result of any function
  			vert.z = abc -- result of any function
  
  			setVert obj v vert
  		)
  		update obj 
  	)
  )