PDA

View Full Version : 3ds max crash/slow when assigning material to 3000 objects


ohls
01-31-2010, 04:11 PM
Hi

I generating around 300 object with a maxscript it takes the material from slot 1 in materialeditor and copy it to the object and then change the diff color. like this
....
$.material = copy meditMaterials[1]
$.material.diff_color = color r g b
....

But 3ds max 2010 x64 crash when I assinging material to so many obects and it's extremly slow.


Is there any better way to assign same material with diffrenct colors?

Bobo
01-31-2010, 07:40 PM
Hi!

Some questions:

*Why are you using $?
*Can we see the actual loop that performs the assignment?
*Have you tried executing the same code inside WITH UNDO OFF () context?

Here is how I would have written it, assuming theObjects is a variable already containing your thousands of objects:


theObjects = selection as array -- grab the current selection into an array
with undo off for o in theObjects do --loop through all objects in the array
(
o.material = copy meditmaterials[1] --assign a copy of the material
o.material.diffusecolor = random black white --this is of course just an example
)


With 10000 objects, it took 5.3 seconds.

ohls
01-31-2010, 08:00 PM
I create a object that is selected and using $ for access it.
I paste the loop if I remove two .material lines than it's fast but when I have them in the script it's really slow. I have't tryed WITH UNDO OFF () but I should try it.

Thanks for the tip.



while not eof cordfile do
(

box widthsegs:1 lengthsegs:1 heightsegs:1 length:6 width:6 height:1 transform:(matrix3 [1,0,0] [0,0,1] [0,-1,0] [0,0,0]) isSelected:on

move $ [x,y,z]
rotate $ (angleaxis (r) [0,0,1])

$.material = copy meditMaterials[1]

$.material.diff_color = color r g b


.....


)

Pjanssen
01-31-2010, 08:02 PM
with redraw off will probably help too ;)

And instead of using the selection, assign the created box to a variable:
local thebox = box()

Bobo
01-31-2010, 08:48 PM
Selecting the object before changing it is a BAD idea. It causes a refresh of the Command Panel and a refresh of the viewport. With thousands of objects, it will waste a lot of time.

MAXScript has great tools to modify objects without them being selected (see my example).

denisT
02-01-2010, 01:58 PM
Hi

I generating around 300 object with a maxscript it takes the material from slot 1 in materialeditor and copy it to the object and then change the diff color. like this
....
$.material = copy meditMaterials[1]
$.material.diff_color = color r g b
....

But 3ds max 2010 x64 crash when I assinging material to so many obects and it's extremly slow.


Is there any better way to assign same material with diffrenct colors?

to create 1000s of objects and materials is not a problem. It's fast. The bottleneck is to add material to scenematerials. Every time when max assigns material to an object it searches in scenematerials for uniqueness, and if scenematerials doesn't contain new material max appends this material to the collection. Also there is another problem. When max deletes any object it doesn't clean scenematerials from "deleted" with the object material. Technically scenematerials can contain not assigned materials.

here is the simple test which shows the problems:

while scenematerials.count > 0 do deleteitem scenematerials 1
mat = Standard()
format ">>>> scene materials: %\n" scenematerials.count

with undo off with redraw off for k=1 to 10 do
(
delete objects
gc()
t1 = timestamp()
for i=1 to 100 do
(
b = box()
b.mat = copy mat
)
format "%: % %\n" k (timestamp() - t1) scenematerials.count
)


and there is no way (at least I don't know) to defeat this behavior.

denisT
02-01-2010, 03:33 PM
theObjects = selection as array -- grab the current selection into an array
with undo off for o in theObjects do --loop through all objects in the array
(
o.material = copy meditmaterials[1] --assign a copy of the material
o.material.diffusecolor = random black white --this is of course just an example
)


With 10000 objects, it took 5.3 seconds.

maybe anything wrong with my system but ...

while scenematerials.count > 0 do deleteitem scenematerials 1
mat = Standard()
format ">>>> scene materials: %\n" scenematerials.count

with undo off with redraw off
(
delete objects
gc()
t1 = timestamp()
for i=1 to 1000 do
(
b = box()
b.mat = copy mat
b.mat.diffusecolor = random black white
)
format "% %\n" (timestamp() - t1) scenematerials.count
)


it takes ~ 9 sec for 1000 nodes on my machine

Bobo
02-01-2010, 03:35 PM
...there is no way (at least I don't know) to defeat this behavior.

The assignment of materials to scene nodes used to be even slower before Max 2008. It caused all kinds of additional updates, including refresh of the 24 MEdit materials once per assignment ;)

The scenematerials data is being cleaned up on a pre-save notification broadcast, so calling HoldMaxFile() or even performing a saveNodes() with an empty array to a temp. file should clean up the mess.

Bobo
02-01-2010, 03:37 PM
maybe anything wrong with my system but ...
...
it takes ~ 9 sec for 1000 nodes on my machine

Nothing wrong with your machine. Your code actually makes the 1000 objects.
My code was measuring the ASSIGNMENT of material to 10K object which already existed.
(As I was arguing that material assignment to a clean object with no material is fast since 2008).
I had the 10K object created by simple manual cloning before I wrote the script... :o)

Then again, running your code on an empty scene on my system produced 1000 objects in 3578 ms.

denisT
02-01-2010, 03:43 PM
The scenematerials data is being cleaned up on a pre-save notification broadcast, ... even performing a saveNodes() with an empty array to a temp. file should clean up the mess.

great trick !!! thanks!

denisT
02-01-2010, 03:52 PM
while scenematerials.count > 0 do deleteitem scenematerials 1
mat = Standard()
format ">>>> scene materials: %\n" scenematerials.count

with undo off with redraw off for k=1 to 5 do
(
delete objects
gc()
t1 = timestamp()
for i=1 to 500 do
(
while scenematerials.count > 0 do deleteitem scenematerials 1
b = box()
b.pos.x += b.width*i
b.mat = copy mat
b.mat.diffusecolor = random black white
)
format "%: % %\n" k (timestamp() - t1) scenematerials.count
)
saveNodes #() (getdir #temp + "\\back.bak") quiet:on
format "<<<< scene materials: %\n" scenematerials.count


great!

ohls
02-02-2010, 09:28 PM
I changes my script with redraw off and undo off and not selecting any objects. But it stills very slow
as denisT (http://forums.cgsociety.org/member.php?u=384956) says the scenmaterial line makes it so slow I think it takes about 10 min to run on 2000 planes.

if I remove this to lines the speed is ok.:
mybox.material = copy meditMaterials[1]
mybox.material.diff_color = color r g b

The speed is ok.






with undo off with redraw off
(

evac =getOpenplanename types:" (*.dat)|*.dat|All Files (*.*)|*.*"

testfile = openFile evac
while not eof testfile do
(


.....


Plane widthsegs:1 lengthsegs:1 length:6 width:6 transform:(matrix3 [1,0,0] [0,0,1] [0,-1,0] [0,0,0])

mybox.material = copy meditMaterials[1]
mybox.material.diff_color = color r g b

move mybox [X,Y,Z]

rotate mybox (angleaxis (z) [0,0,1])


)

)

denisT
02-02-2010, 09:48 PM
but you are not assigning newly created plane to mybox. that means new material doesn't go in scene materials list.

CGTalk Moderation
02-02-2010, 09:48 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.