Notifications
Clear all

[Closed] How to fast search material ID from objects

I am biggner with max script.
and also my english is not good.
sorry for that maybe sometime you don’t understand my english.
bty
i have several scenes containing objects ranging from 2000 objects to 5000 objects.
and i have to scearch material ID from all of objects in scene.
so i made this script.
and finally i want to goal that i want to select object when push the material ID channel button from this script.
but it’s very slow.
I want to make this script work faster.
do you have any idea.

————– script ————–
ChannelObjArr = #() –400 channel array
errorObj =#()

for n =1 to 400 do
(
	emptySpace = #()
	append ChannelObjArr emptySpace 
)

	
for g=1 to geometry.count do
(
	
	
	if classof geometry[g] == Editable_mesh do
	(
		OneChArr = for f =1 to getNumFaces geometry[g] collect getFaceMatID geometry[g] f
	)
	if classof geometry[g] == Editable_Poly or classof geometry[g] == PolyMeshObject do
	(
		OneChArr = for f =1 to getNumFaces geometry[g] collect polyop.GetFaceMatID geometry[g] f
	)
	
	try ( makeuniquearray OneChArr ) catch ( append errorObj geometry[g])
	
	
	for n in OneChArr do
	(
		appendifunique ChannelObjArr[n] geometry[g]
	)
	
)

14 Replies

Trimesh snapshots should be enough for the task

delete objects
gc()

seed 42

for i = 1 to 666 do
(
	addModifier (Teapot pos:(random [0,0,0] [1000,1000,1000])) (MaterialByElement Material_ID_Count:(random 1 7))
)


fn GetUsedMtlIDs node = 
(
	if isValidNode node and canConvertTo node Editable_mesh do
	(
		local tri = snapshotAsMesh node		
		local mtl_ids = #{}

		for f = 1 to tri.numfaces do mtl_ids[ getFaceMatID tri f ] = true		
		
		free tri	
		mtl_ids
	)
)


t1=timestamp();hf = heapfree

node_material_ids = for n in geometry collect DataPair node:n mtlid:(GetUsedMtlIDs n)
	
format "1. Time: %sec. Mem: %\n" ((timestamp()-t1)/1000 as float) (hf-heapfree)

nodes_by_material_id = #()

for item in node_material_ids do
(
	for id in item.mtlid do
	(
		if nodes_by_material_id[ id ] == undefined then nodes_by_material_id[ id ] = #( item.node ) else append nodes_by_material_id[ id ] item.node
	)
)

select nodes_by_material_id[5]

i don’t know all of your script.
for example gc() , isValidNode , canConvertTo.
this is not common for me and it need study.
so instead i edit my script with SnapshotAsMesh.
and it’s working fast more before my script.
thak you guys.
sorry poor english.

There is no reason to snapshot as mesh.

mode.mesh -- it's enough 
1 Reply
(@serejah)
Joined: 10 months ago

Posts: 0

Yes, if used for geometry exclusively.

But to get mtl IDs from shapes it is still convenient to use it. It has no big impact on performance anyway (at least not in simple synthetic tests).

(egg render_renderable:true).mesh -- -- Runtime error: Cannot get mesh from this object: Egg

snapshot makes a copy of mesh and a copy of mesh value. It’s a big difference for large meshes when you use .mesh pointer instead.

delete objects
ss = for k=1 to 50 collect (geosphere segs:200)

gc()

(
	t0 = timestamp()
	h0 = heapfree

	for s in ss do
	(
		m = snapshotasmesh s
		free m
		--m = s.mesh
	)

	format "time:% heap:%\n" (timestamp() - t0) (h0 - heapfree)
)

yeah, when node has no modifiers in stack getting .mesh is instant compared to snapshotasmesh

snapshotasmesh is usually good to use when you need to access geometry in #world coordinates to avoid additional computation to translate from the local coordinate system (where .mesh). In general, it is always slower than .mesh.

If you need to iterate the mesh faces, edges verts, etc. you should use snapshotasmesh(), even if it has no modifiers.


PRIMITIVE

(
	delete objects
	
	gc()
	st=timestamp(); sh=heapfree
	
	node = teapot segs:16
	
	m = node.mesh
-- 	m = snapshotasmesh node
	
	for j = 1 to m.numfaces do getfacematid m j
	for j = 1 to m.numverts do getvert m j
	
	format "time:% heap:%\n" (timestamp()-st) (sh-heapfree)
)

node.mesh
time:1708 heap:480L

snapshotasmesh node
time:6 heap:480L


EDITABLE_MESH

(
	delete objects
	
	gc()
	st=timestamp(); sh=heapfree
	
	node = converttomesh (teapot segs:64)
	
	m = node.mesh
-- 	m = snapshotasmesh node
	
	for j = 1 to m.numfaces do getfacematid m j
	for j = 1 to m.numverts do getvert m j
	
	format "time:% heap:%\n" (timestamp()-st) (sh-heapfree)
)

node.mesh
time:130 heap:10083024L

snapshotasmesh node
time:113 heap:10083024L


EDITABLE_POLY

(
	delete objects
	
	gc()
	st=timestamp(); sh=heapfree
	
	node = converttopoly (teapot segs:16)
	
	m = node.mesh
-- 	m = snapshotasmesh node
	
	for j = 1 to m.numfaces do getfacematid m j
	for j = 1 to m.numverts do getvert m j
	
	format "time:% heap:%\n" (timestamp()-st) (sh-heapfree)
)

node.mesh
time:18085 heap:480L

snapshotasmesh node
time:19 heap:480L

You compare wrong things… I said about a time to get access to the mesh. It makes sense to compare multiple objects as it is in the original question.

    for s in ss do
	(
		m = snapshotasmesh s
		free m
		--m = s.mesh
	)

PS. if you are interested I can explain why in your example using .mesh is so slower than using snapshot

2 Replies
(@denist)
Joined: 10 months ago

Posts: 0

node.mesh is an ‘live’ bridge to geometry mesh data. It’s opened for ‘read’ and ‘write’ and when you use it with ‘at time context’ for example you don’t need to call for new access every time how you have to do in ‘snapshot’ case.
If you need static state of the mesh you can use its copy:

m = copy node.mesh

It will make a data pointer similar to snapshot. But snapshot also includes translation of the mesh do #world coordinate system. This makes in general snapshot slower.

(@polytools3d)
Joined: 10 months ago

Posts: 0

It could but it’s not.

You made one statement and your code supports it. I made a completely different statement and my code supports it, so there is nothing wrong with it.

node.mesh property is almost useless (except in a few cases). A copy of node.mesh property is a different thing and while we can use it I don’t do it unless I need to get the untransformed data.

A copy of node.mesh is faster than snapshotasmesh() because it does not apply any transformation, but it isn’t actually too much faster.
(snapshotasmesh source code in the SDK)

So my advice is still to use snapshotasmesh(), moreover for someone that is starting to code in MXS.

@PolyTools3D try gettrimesh from my lib. It’s .mesh but with fixed bug

Page 1 / 2