[Closed] Performance-Problems and MaterialIDs
Hi there,
i am currently working on a script, that gives the user a “select by materialID” functionality for multiple objects at once. You type in an ID and the script selects all objects, that use that id on at least one face (it also selects objects with multiple IDs, if it has at least one poly, that has the specified MaterialID)
Right now i am doing it as following:
I create an empty array for the selection to come
I run a for loop for all objects in the ObjectSet “Geometry”
For every single Object i run a for loop, that looks through all the objects Polys with
getFaceMatID e.mesh poly.index
and if that has the MatID i am looking for, i append the current Object to the selection-array and break the poly-for-loop to save some processing.
After all is done, i select all the objects in the array.
That works…for smaller scenes…but it crashes my computer for bigger scenes with many single objects by creating some kind of memory-overflow.
I can understand, why it takes huge amounts of RAM (more then 15 GB) on scenes with 100 and more objects, that can have more then 1500 Polys each. It has to touch all objects and keeps them in the RAM for as long as the loop runs…but there has to be a way to make things more efficient.
Do i really have to run through all the polys and ask for the MatID to get what i need? When i select an Editable_Poly, there is a drop-down-list in the MatID-Section, that lists all used MatIDs of the current Object…and it does so fast. I suppose, it doesnt run through all the polys to fill that list, but has some kind of index or meta-information on the object itself.
It would be great, if i could access this info somehow…would save me a for-loop and a whole lot of memory.
Other then that, it would be cool, if i could perform some kind of memory-release for each object, i processed, so that the script-engine doesn´t have to hold all the objects in the RAM for the time, the script runs.
I hope you can give me a hint or two
Try this code:
(
st = timestamp()
local needObj = #()
WM_SETREDRAW=0xB
commandHWND = windows.getChildHWND #max "Command Panel"
for o in geometry do
(
addmodifier o (VolumeSelect level:2 volume:5 matID:10)
addModifier o (Mesh_Select ())
if (getFaceSelection o).numberset != 0 do append needObj o
deleteModifier o 1
deleteModifier o 1
)
select needObj
windows.sendmessage commandHWND[1] WM_SETREDRAW 1 0
end = timestamp()
format "time: %
" ((end-st)/1000.0)
)
I tested it on a scene with 70 editable_poly objects(standart Teapot with TS with 1 iteration = 8064 faces for teapot) and 70 editable_mesh objects(standart Teapot with TS with 1 iteration = 4032 faces for teapot), total polycount 635 040. My PC is old(RAM 1,5GB DDR), but the time to select desired objects is 6.609 sec.
Thanks to denisT for showing me how to stop comand panel flickering.
every time you use the .mesh property you are creating a copy of the object’s mesh, so you are effectively creating 1 new mesh in memory for each face that you loop over! i think it would be better to use snapshotasmesh <object> which returns a trimesh and then looping over that. and when you’re done, use either free or delete on the trimesh to free up the memory. There are probably a few more little things you can do for maximum efficiency but this should get you off to a good start
As Gravey suggest:
(
st = timestamp()
local needObj = #()
local getFaceCount = getNumFaces
local getFaceMatIDs = getFaceMatID
for o in geometry do
(
tm = snapshotasmesh o
notFound = true
for f in 1 to (getFaceCount tm) while notFound where (getFaceMatIDs tm f) == 2 do
(
append needObj o
notFound = false
)
delete tm
)
select needObj
end = timestamp()
format "time: %
" ((end-st)/1000.0)
)
Much faster.
That sounds awesome…
thanks for clearing things up. I knew i was doing quite inefficient stuff there, but i didn´t know how to do things better. I will look into the code for sure and try to understand all of it. Thanks for the help!
I tried the code miauu sugested first and it works great except one thing:
The Method to prevent the command panel redraw isn´t working....reason: It can´t find the Command Panel
The function returned undefined and i tried to look up, where the error might be. By running
print (windows.getChildrenHWND #max)
i got all the Windows associated to 3ds…and the command panel isn´t part of that.
It is actively shown…but not docked…
Can someone explain me why? I´m on Max 2011 x64 if that matters
EDIT:
Solved it!
It is because my Command Panel isn´t docked…it isn´t part of Max´s hierarchy then…it is another parent window like the Max-Mainwindow itself. I´ll try and implement an if-clause to check for that too, in case the original code returns an undefined.
Thanks very much for that code anyway…it´s very efficient now.
The second code does not “work” with command panel. The first one try to stop flickering, but the second code is much much faster.
in case the original code of Gravey returns an undefined.
The code is mine, Gravey sugegst to use snapshotAsMesh. So if the code return undefined you have to blame me.
Thanks…i edited the posts…lost track of the names in my rush
I will try and compare both methodes. The snapshot-mesh-thingy sounds interesting, because i am planning on expanding the script in that way, that it is able to detach the parts of a mesh with multiple MatIDs, that have the specified MatID assigned.
Edit:
Ran a few tests. The first code of miauu is around 4 times faster then garveys approach with the snapshot-meshes.
Working with the two modifieres on a scene with 3358 complex objects and a poly-count of around 4.700.000 takes around 3.9 seconds to select the 1919 Objects that have a MatID of 1, while the aproach with the snapshot-mesh takes around 12.4 seconds to achieve the same thing.
Thanks for all that anyway…i really learned a lot about what Max does internally
Thanks…i edited the posts…lost track of the names in my rush
Look again.
The two codes in this thread are mine – with the two modifiers and with “snapshotAsMesh”.
On my max2009, in the scene that i describe in my first post: 70 editable_poly objects(standart Teapot with TS with 1 iteration = 8064 faces for teapot) and 70 editable_mesh objects(standart Teapot with TS with 1 iteration = 4032 faces for teapot), total polycount 635 040 and 140 objects, the first code(with 2 modifiers) took ~6,7 sec, the second code(with snapshotasmesh) took ~ 2 sec.
But the speed of the two code depends of the scena and the objects that you have.
Interesting thing with the differences
I will stick with the first approach, as it seems to fit my scenario for most of the time. Thanks again.
Sorry for the naming-clutter. It´s almost weekend…and i need the weekend soon…hope that is a valid excuse