Notifications
Clear all

[Closed] vray MultiMatteElement from Layer

 Rav

Hi,
I have found a script, it creates a MultiMatteElement pass from your layers, and applies object id’s to the geometry.

The problem i have with this is, when i have a scene, with particles and forest pack objects it errors out.

Is there away to have the script to apply only to geometry objects and shapes? in the scene?

heres the script:

clearlistener()

fn keepChars str pass: = (
local killChars = case pass of
(
1: "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ!()*- /@" 
2: "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ!()*- /@"
3: "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ!()*- /@"
)
for i = str.count to 1 by -1 where (local index = findString killChars str[i]) == undefined do str = replace str i 1 ""
str
)

fn cropString str charMax = (

if str.count > charMax then
(
str = keepChars str pass:1
if str.count >charMax then
(
str = keepChars str pass:2
if str.count > charMax then
(
str = keepChars str pass:3
if str.count > charMax then
(
str = substring str 1 charMax
)
else str
)
else str
)
else str
)
str
)

fn removeElementByPrefix pref = (
clearlistener()
local re = maxOps.GetCurRenderElementMgr() 

for i = re.numrenderelements()-1 to 0 by -1 do
(
x = (re.GetRenderElement i)
elName = x.elementName

prefix = substring elName 1 pref.count

if prefix == pref do
(
format "Removing element %

" elName
re.REmoveRenderElement x
)
)

)



(
local re = maxOps.GetCurRenderElementMgr() 
local el = multimatteelement
local groupsSoFar = 0 
--starting ID's number
local startID = 00
--MultiMatteElement name remove
removeElementByPrefix "matte_"

for el = 1 to re.numrenderelements() do
(
re.GetRenderElement el
)

while groupsSoFar*3 < layerManager.count-1 do 
(
layerGroup = ""
idGroup = #()
for i = 1 to 3 while (x = i+groupsSoFar*3) <= layerManager.count-1 do
(

layer = ILayerManager.getLayerObject x
layerRefs = refs.dependents layer
layerName = (cropString ((layerManager.getLayer x).name) 9)
layerNodes = #()

layerGroup += layerName
append idGroup (startID + x)

for o in layerRefs where classof (superClassOf o) == node and superclassof o == GeometryClass do
(
append layerNodes o 
)
----help????
for obj = 1 to layerNodes.count do
(
if layerNodes[obj] != "shapes" do 
(
layerNodes[obj].gbufferChannel = x
)

)
format "LayerRefs: %
" layerRefs
format "Layer: %
" layerName
format "Objects: %
" layerNodes
format "ObjectID: %
" x
)

if idGroup.count < 3 do
(
append idGroup (idGroup[idGroup.count] + 1)
if idGroup.count < 3 then 
(
append idGroup (idGroup[idGroup.count] + 1)
)
else()
)
---Name_Pass
layerGroup = "matte_" + layerGroup
format "MultiMatte name: % is % characters.
" layerGroup layerGroup.count
format "IDs in MM: %

" idGroup
format "--------------------

"

if groupsSoFar*3 < layerManager.count-1 do
(
re.addrenderelement (el elementname:layerGroup R_gbufID:idGroup[1] R_gbufIDOn:(on) G_gbufID:idGroup[2] G_gbufIDOn:(on) B_gbufID:idGroup[3] B_gbufIDOn:(on) )	
)

groupsSoFar +=1 --increment the groups counter
)	
)

Thanks

10 Replies

If several Classes falls into the same Superclass and you need to filter them, one way I can think of is to have either a “whitelist” or a “blacklist” of Classes, the shortest or the safest one, depending on what information of the scene you have. It might not be elegant but could work.

This function uses a blacklist to filter out the default Particles Systems:

(
 fn GetSceneNodes =
 (
 	blacklist =
 	#(
 		pf_source,
 		particlegroup,
 		snow,
 		blizzard,
 		pcloud,
 		spray,
 		superspray,
 		parray
 	)
 	
 	layernodes = #()
 	for o in objects where iskindof o node do
 	(
 		if superclassof o == geometryclass do
 		(
 			if finditem blacklist (classof o) == 0 do append layernodes o
 		)
 	)
 	return layernodes
 )
 nodes = GetSceneNodes()
 )

This other function uses a whitelist to collect some of the Geometry Classes and Shapes:

(
 fn GetSceneNodes =
 (
 	whitelist =
 	#(
 		polymeshobject,
 		editable_mesh,
 		editable_poly
 	)
 	
 	layernodes = #()
 	for o in objects where iskindof o node do
 	(
 		if finditem whitelist (classof o) != 0 or superclassof o == shape do append layernodes o
 	)
 	return layernodes
 )
 nodes = GetSceneNodes()
 )
3 Replies
(@gazybara)
Joined: 11 months ago

Posts: 0

Or simply

fn GetSceneNodes =
 (
 	fn filterGeo node = ((node.category != #Itoo_Software or node.category != #Particle_Systems) and canconvertto node Editable_Mesh)
 	for o in objects where filterGeo o collect o
 ) 
nodes = GetSceneNodes ()

(@polytools3d)
Joined: 11 months ago

Posts: 0

Couldn’t it happen that certain Particle System plugins don’t use the #Particle_Systems category and use a different one?

(@gazybara)
Joined: 11 months ago

Posts: 0

I don’t know. Maybe but I did’nt use such P-System. Anyway… We can always put one more item in the “exclude” lisr. Right?

 Rav

Thank you PolyTools3D,
just abit stuck as, were to put that into the script?

Im not very proficient with maxscripting

Good question!
I am not entirely sure of how the function works nor do I have a proper scene to fully test it, but I guess that for Meshes, Polys and Shapes the following code should work:

clearlistener()
 
 fn keepChars str pass: = (
 	local killChars = case pass of
 	(
 		1: "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLM  NOPQRSTUVWXYZ!()*- /@" 
 		2: "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLM  NOPQRSTUVWXYZ!()*- /@"
 		3: "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLM  NOPQRSTUVWXYZ!()*- /@"
 	)
 	for i = str.count to 1 by -1 where (local index = findString killChars str[i]) == undefined do str = replace str i 1 ""
 	str
 )
 
 fn cropString str charMax = (
 	if str.count > charMax then
 	(
 		str = keepChars str pass:1
 		if str.count >charMax then
 		(
 			str = keepChars str pass:2
 			if str.count > charMax then
 			(
 				str = keepChars str pass:3
 				if str.count > charMax then
 				(
 					str = substring str 1 charMax
 				)
 				else str
 			)
 			else str
 		)
 		else str
 	)
 	str
 )
 
 fn removeElementByPrefix pref = (
 	
 	clearlistener()
 	local re = maxOps.GetCurRenderElementMgr() 
 
 	for i = re.numrenderelements()-1 to 0 by -1 do
 	(
 		x = (re.GetRenderElement i)
 		elName = x.elementName
 
 		prefix = substring elName 1 pref.count
 
 		if prefix == pref do
 		(
 			format "Removing element %

" elName
 			re.REmoveRenderElement x
 		)
 	)
 )
 
 
 
 (
 	
 	local re = maxOps.GetCurRenderElementMgr() 
 	local el = multimatteelement
 	local groupsSoFar = 0 
 	--starting ID's number
 	local startID = 00
 	--MultiMatteElement name remove
 		
 	local whitelist =
 	#(
 		polymeshobject,
 		editable_mesh,
 		editable_poly
 	)
 
 	removeElementByPrefix "matte_"
 
 	for el = 1 to re.numrenderelements() do
 	(
 		re.GetRenderElement el
 	)
 
 	while groupsSoFar*3 < layerManager.count-1 do 
 	(
 		layerGroup = ""
 		idGroup = #()
 		
 		for i = 1 to 3 while (x = i+groupsSoFar*3) <= layerManager.count-1 do
 		(
 			layer = ILayerManager.getLayerObject x
 			layerRefs = refs.dependents layer
 			layerName = (cropString ((layerManager.getLayer x).name) 9)
 			layerNodes = #()
 
 			layerGroup += layerName
 			append idGroup (startID + x)
 
 -- 			for o in layerRefs where classof (superClassOf o) == node and superclassof o == GeometryClass do
 -- 			(
 -- 				append layerNodes o 
 -- 			)
 
 			for o in layerRefs where iskindof o node do
 			(
 				if finditem whitelist (classof o) != 0 or superclassof o == shape do append layerNodes o
 			)
 			
 			----help????
 			for obj = 1 to layerNodes.count do
 			(
 				if layerNodes[obj] != "shapes" do 
 				(
 					layerNodes[obj].gbufferChannel = x
 				)
 			)
 			format "LayerRefs: %
" layerRefs
 			format "Layer: %
" layerName
 			format "Objects: %
" layerNodes
 			format "ObjectID: %
" x
 		)
 
 		if idGroup.count < 3 do
 		(
 			append idGroup (idGroup[idGroup.count] + 1)
 			if idGroup.count < 3 then 
 			(
 				append idGroup (idGroup[idGroup.count] + 1)
 			)
 			else()
 		)
 		
 		---Name_Pass
 		layerGroup = "matte_" + layerGroup
 		format "MultiMatte name: % is % characters.
" layerGroup layerGroup.count
 		format "IDs in MM: %

" idGroup
 		format "--------------------

"
 
 		if groupsSoFar*3 < layerManager.count-1 do
 		(
 			re.addrenderelement (el elementname:layerGroup R_gbufID:idGroup[1] R_gbufIDOn:(on) G_gbufID:idGroup[2] G_gbufIDOn:(on) B_gbufID:idGroup[3] B_gbufIDOn:(on) )	
 		)
 		
 		groupsSoFar +=1 --increment the groups counter
 		
 	)
 	
 )
1 Reply
 Rav
(@rav)
Joined: 11 months ago

Posts: 0

Thanks PolyTools3D, works perfectly, tired testing in various scenes and hasn’t broken yet

Of course. The OP can add as many things as needed, depending on what the scenes contains and what needs to be excluded. That’s why my suggestion of blacklisting or whitelisting. I would believe that most scenes would use polys or meshes, but that’s far away from been accurate, as I have no idea of what other artists/developers have in their scenes.

They could use a load of custom or commercial plugins that I we are not aware of. For example, as I don’t have Forest Pack to test it, I have no idea of what you can build with it or if everything you can build with it will fall into the #Itoo_Software category.

2 Replies
(@gazybara)
Joined: 11 months ago

Posts: 0

I agree.
Also every user which use 3d party plugs that causing similar problems can also learn a simple line of mxs code ($.category) to find object category and simply isolate it from the process.

(@polytools3d)
Joined: 11 months ago

Posts: 0

Personally I wouldn’t rely that much just in the “Category” of a node. See the following very simple example:

(
 	delete objects
 	pf_source logo_size:25 emitter_length:50 emitter_width:50
 
 	for node in objects do
 	(
 		format "class:%		category:%
" (classof node) node.category
 	)
 )