ScriptSpot

Forum topic · Scripts Wanted

I need a little script to delete last MatID(Mesh)

By DolVai · 2013-03-03

Description

Hello, i spent a lot of time on making this stuff and first time i release it, but second i couldn't make it again,
to delete last MatID(mesh) by 1 click, can someone help me with this ?
IT's a simple script when you select a mesh and press button - it deletes last MaTID(mesh).

P.S.

And if it possible http://dfiles.ru/files/owsepv1vr to modifie this script(its .psk file importer) and add to it a possibility to insert special mesh(On the importing model), while importing the file, with position controlling rulers.

Comments (24)

it works

DolVai · 2013-03-04

Thx! it works,

Second question, http://dfiles.ru/files/owsepv1vr is it possible to modifie this script, it is importing psk files(that have mesh, bones and skin data)
I need a little modification, to attach a mesh(from folder - in 3ds format or obj) on import and to be able to change it's position using script ?

I'm in need of this for a long time, 3-6 months.

Thx guys anyway! for your time and work its helps me a lot.

Hey Artemie

barigazy · 2013-03-04

Why don't you ask the author to add new features that you suggested

DolVai · 2013-03-05

I did asked him, he doesn't have 3ds max anymore and he won't install it, if this future will be available it would save a lot of time,

or is to hard ?

Skin problem

DolVai · 2013-03-04

--Update guys,

this script works perfectly even for meshes with skin modifier applied on!

fn delMeshFaces obj =
(
	local getFID = getFaceMatID, idArr = #(), lastID = 0, aFaces = #()
	for i = 1 to obj.numfaces where ((id = getFID obj i) > lastID) do lastID = id
	for f = 1 to obj.numFaces where getFID obj f == lastID do append aFaces f ;
	meshop.deleteFaces obj aFaces
)

Hey thx guys for helping me out, but seems script won't work with skin modifier applied on mesh http://i.imgur.com/ZOMKUIL.png
Is it possible to add little support - with skin applied ?

I tested anubis script on max 9 and its didn't work =(.

the script from the PNG is not mine ;-)

Anubis · 2013-03-04

it was made by Branko and he already update and fixed it, so it works too now in Max 9, but the script you post above is mine, with some additional optimization mades by Branko, and if it works fine, then where is the problem?

try now

barigazy · 2013-03-04


fn delMeshFaces obj =
(
local getFID = getFaceMatID, idArr = #(), lastID = 0, aFaces = #()
for i = 1 to obj.numfaces where ((id = getFID obj i) > lastID) do lastID = id
for f = 1 to obj.numFaces where getFID obj f == lastID do append aFaces f ;
meshop.deleteFaces obj.baseobject aFaces ; update obj
)

barigazy · 2013-03-03

This is my test. Based on your solution I fixed memory lecking
First test scene (10 collapsed boxes)


delete objects
testmesh = Editable_Mesh()
for m = 1 to 10 do attach testmesh (box lengthsegs:10 widthsegs:10 heightsegs:10 pos:[(m-1)*30,0,0])
select testmesh

Now your original code #1 solution


fn delfaces obj = 
(
	local lastID = 0, currID, aFaces, getFID = getFaceMatID
	for f = 1 to obj.numFaces do
	if (currID = getFaceMatID obj f) > lastID do
		lastID = currID
	aFaces = for f = 1 to obj.numFaces where \
	(currID = getFaceMatID obj f) == lastID \
		collect f
	meshop.deleteFaces obj aFaces
)

This is recreation of your code #2 solution


fn delMeshFaces obj =
(
	local getFID = getFaceMatID, idArr = #(), lastID = 0, aFaces = #()
	for i = 1 to obj.numfaces where ((id = getFID obj i) > lastID) do lastID = id
	for f = 1 to obj.numFaces where getFID obj f == lastID do append aFaces f ;
	meshop.deleteFaces obj aFaces
)

And now the result
#1 solution


gc()
t1 = timestamp()
m1 = heapfree
delfaces testmesh
format "time:% memory:%\n" ((timestamp()- t1 as float)/1000) (m1-heapfree)
update testmesh
time:0.064 memory:1485368L

#2 solution


gc()
t1 = timestamp()
m1 = heapfree
delMeshFaces testmesh testmesh
format "time:% memory:%\n" ((timestamp()- t1 as float)/1000) (m1-heapfree)
update testmesh
time:time:0.048 memory:129824L

#2 solution is 10 time memory efficient and 1/3 time faster

thanks for testing

Anubis · 2013-03-03

Interesting, I always thought that Collect is more faster than Append. Maybe I s'd test them again.

barigazy · 2013-03-03

This is the replacement for "appendIfUnique"


obj = $
arr = #()
objFaceIDs = for f in 1 to obj.numfaces where (finditem arr (hVal = gethashvalue (fID = (getFaceMatID obj f)) 0)) == 0
collect ( append arr hVal ; fID)

and the final code will be

try(destroydialog ::testRoll) catch()
rollout testRoll "Delete LastMTLID Faces"
(
fn deleteLastMtlIDfaces obj =
(
local arr = #()
objFaceIDs = for f in 1 to obj.numfaces where (finditem arr (hVal = gethashvalue (fID = (getFaceMatID obj f)) 0)) == 0 collect (append arr hVal ; fID)
for f in 1 to obj.numfaces do appendIfUnique arr (getFaceMatID obj f)
lastIDFaces = sort (for f = 1 to obj.numfaces where (getFaceMatID obj f) == (amax objFaceIDs) collect f)
for f = lastIDFaces.count to 1 by -1 do deleteFace obj lastIDFaces[f]
free arr ; free objFaceIDs ; update obj
)
button theButton "Do the JOB!" pos:[5,5] width:140 height:40

on theButton pressed do
(
if selection.count != 0 do
(
for o in selection where iskindof o Editable_Mesh do deleteLastMtlIDfaces o
)
)
)
createDialog testRoll 150 50 10 110 style:#(#style_titlebar, #style_sysmenu, #style_toolwindow)

Anubis · 2013-03-03

Did you tested my example function I post below?

I'm just curious is it worth :)

barigazy · 2013-03-03

Yes i tested it. Also i check time and memory leaking and you have better solution for sure. Memory leak is the main problem in this aproch.

:)

barigazy · 2013-03-03

Hey, how do you setup "post below" hyperlink. Very cool

[link to this post is here]

Anubis · 2013-03-03

Each post has link in it title ;-)

barigazy · 2013-03-04

No "append" is fester from "collect" probable because for append method you already have defined array and for collect you build array on the fly.
Also is better to store mesh fn in local variable before use it multiple time (in for-loop or while-loop etc..).
By the way, is there easy way to get bigest mtlID number of geometry object.
I think that's poly method is more efficient (numFaces count is twice lower).

LOL

Anubis · 2013-03-04

I'm sure that I done some test in the past to end with such conclusion that Collect is faster than Append :) Anyway, will test once again (some day).

Storing a function in variable,.. ya I know that helps in case the function is a Struct member, like meshOps for example, but not thought to test that for other (stay-alone) functions. So, it's help for them too?

As for easy way to get bigest mtlID, well,.. it's what I use in my function (for..if..x>y..y=x), at least don't know better :) We have #materialIDs named-prop in Mesh Constructor, but we cannot access it after that (on existing mesh), so sad, and the great ADSK is so lazy to make that property script-visible. If were exposed then all to code w'd been just this:

amax m.materialIDs

but... :)

:)))

barigazy · 2013-03-04

Hey Panayot,
I know. I agree with you (laziness is a bad habit) :).
Also I wonder when Phyton become part of max. Like in Maya or Softimage or Cinema4d or Blender or ... 10 more softwares. .net is very useful but phyton ...

:)

barigazy · 2013-03-03

Sorry i forget to replace "$" with "obj" variable.
I fixed the code try now.
Try to avoid objects that have only one mtlID

are you in Max 9 or below?

Anubis · 2013-03-03

if so, there no

appendIfUnique

function, at least until install AVG (Avguard Extensions).

barigazy · 2013-03-03

Yep. I think that "apendIfUnique" cause the problem here

barigazy · 2013-03-03

You asked a script. Here we go

try(destroydialog ::testRoll) catch()
rollout testRoll "Delete LastMTLID Faces"
(
fn deleteLastMtlIDfaces obj =
(
local arr = #()
for f in 1 to obj.numfaces do appendIfUnique arr (getFaceMatID obj f)
lastIDFaces = sort (for f = 1 to obj.numfaces where (getFaceMatID obj f) == (amax arr) collect f)
for f = lastIDFaces.count to 1 by -1 do deleteFace obj lastIDFaces[f]
update obj
)
button theButton "Do the JOB!" pos:[5,5] width:140 height:40

on theButton pressed do
(
if selection.count != 0 do
(
for o in selection where iskindof o Editable_Mesh do deleteLastMtlIDfaces o
)
)
)
createDialog testRoll 150 50 10 110 style:#(#style_titlebar, #style_sysmenu, #style_toolwindow)

I see you already helps here

Anubis · 2013-03-03

The term "last MatID" is very funny... I need to read your code to see that this is translates as "most higher MatID" :)

Anyway, is next (untested) function is more optimized?

fn delfaces obj = (
	local lastID = 0, currID, aFaces
	for f = 1 to obj.numFaces do
	if (currID = getFaceMatID obj f) > lastID do
		lastID = currID
	aFaces = for f = 1 to obj.numFaces where \
	(currID = getFaceMatID obj f) == lastID \
		collect f
	meshop.deleteFaces obj aFaces
)

try this one

barigazy · 2013-03-03


fn deleteLastMtlIDfaces obj = if iskindof obj Editable_Mesh do
(
local arr = #()
for f in 1 to obj.numfaces do appendIfUnique arr (getFaceMatID $ f)
lastIDFaces = sort (for f = 1 to obj.numfaces where (getFaceMatID $ f) == (amax arr) collect f)
for f = lastIDFaces.count to 1 by -1 do deleteFace obj lastIDFaces[f]
update obj
)
--example
deleteLastMtlIDfaces $