PDA

View Full Version : Delete Selected Objects that have no Faces


David1000
08-16-2007, 02:19 AM
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. :scream:

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

erilaz
08-16-2007, 06:13 AM
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.

David1000
08-16-2007, 02:04 PM
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

erilaz
08-16-2007, 02:42 PM
I'll have a look into it tomorrow if someone doesn't get there before me. :)

erilaz
08-17-2007, 04:35 AM
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:

David1000
08-18-2007, 01:05 AM
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 ?

magicm
08-18-2007, 02:12 AM
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

David1000
08-18-2007, 02:33 AM
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?

magicm
08-18-2007, 12:17 PM
* Did you consider that meshes are inside of groups?
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.

* Did I have to exchange you code line anywhere within the other code examples?
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

David1000
08-18-2007, 02:15 PM
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
)
)

CGTalk Moderation
08-18-2007, 02:15 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.