Another post from CGTalk….
I’m being a bit lazy so I thought I’d ask you clever peeps if there was a way to do the following:
I have a number of Selection Sets which I would like to create ‘Matte’ Render Elements from. Currently I’m doing it manually by creating the ‘Matte’ Render Element and then choosing a Selection Set from the list to include in the Render Element.
If there was a way to automate creation of a ‘Matte’ Render Elements directly from the list of Selection Sets on a 1 to 1 mapping basis (if you know what I mean) this would greatly speed up my workflow.
Any thoughts or ideas mucho appreciated!!!
A nice simple problem to solve… Lets think through the logical steps if we were doing this manually. This is for Mental Ray but wouldn’t take much to adapt it to VRay.
For every selection set…
Take all the objects in that set and set their gbufferID to ‘x’
Add a new Matte render element
Give the render element a unique name “Matte_” + x
Turn on the use GBufferID
Set the render element GBufferID to ‘x’
So lets translate that into a real script…
( re = maxOps.GetCurRenderElementMgr() for i = 1 to selectionsets.count do ( for o in selectionsets[i] do o.gbufferchannel = i re.addrenderelement (MatteRenderElement()) theelement = re.getrenderelement (re.numrenderelements() - 1 ) theelement.elementname = ("Matte_" + i as string) theelement.gbufIDOn = true theelement.gbufID = i ) )
Lets break it down….
re = maxOps.GetCurRenderElementMgr()
In this example the first thing we need to do is get an instance of the render element manager interface.. sounds a bit complicated but it’s to do with different production renderers, draft renderers and activeshade settings from legacy versions of max.
for i = 1 to selectionsets.count do
Next we use an itteration loop, for i = 1 to the count of the selection sets to go through every selection set, we’ve used a for i =1 to loop this time because we need the index value later in the script.
for o in selectionsets[i] do o.gbufferchannel = i
Next we get all the objects in the selection set and set the gbufferchannel, to find out this property you can’t do showproperties…. either look in the help or turn the macroreader on (I’ll cover this better another day). We use a for o in loop as we just want to grab each item and don’t care what number it is, and we can set the gbufferchannel to i as this is the index of the render element we’re going to add.
Re is our render element manager, useful to define shorthand variables for things with long names that you have to type lots! Look in the help file and you’ll see the functions for this interface… re.addrenderelement wants a render element as an argument, note the brackets, (MatteRenderElement()) we need the brackets to evaluate the new render element before we can add it to the list, the () tell max that we want a new object (as in object-orientated programming, not 3dsmax object).
theelement = re.getrenderelement (re.numrenderelements() - 1 )
Next we have to get access to our newly made render element, slightly awkwardly we have to ‘get’ it… using getrenderelement which wants an integer (whole number) as its argument, this index is 0-based, which means the first render element is , the 2nd is . Most of max avoids this 0-based indexing until you start to look at more complicated dotNet programming. I won’t go into the why… it bores me too much, just be aware certain things are 0-based. So to get the index of the newly created render element we get the number of render elements which is now 1, but need to subtract 1 to get our index, hence the – 1. (Note be careful to write – 1 not -1, the lack of space will cause an issue)
theelement.elementname = ("Matte_" + i as string)
Now we have an element we can give it a name, otherwise we’ll get conflicting filenames when we render our file. We want to have “Matte_1”, “Matte_2”, “Matte_3”, so we can just put together the “Matte_” with our index i, but as our i index’s type is integer (whole numbers) we have to tell maxscript to convert this to a string value (think text) to be able to join the two together.
theelement.gbufIDOn = true
Next set the gbufIDOn to true… to get the properties of this render element you can do Showproperties (MatteRenderElement()) and we get the list of the properties.
theelement.gbufID = i
And finally lets set the gbuffer ID.
Now there’s a small bit of optimization we can do which shortens the script, but doesn’t make it quite as readable, when you create a max-object, MatteRenderElement() you can replace the () with a set on parameters you want to set on creation…. so we could cut the script to this…
( re = maxOps.GetCurRenderElementMgr() for i = 1 to selectionsets.count do ( for o in selectionsets[i] do o.gbufferchannel = i re.addrenderelement (MatteRenderElement elementname:("Matte_" + i as string) gbufIDon:true gbbufID:i) ) )
There is no way AFAIK to refresh the Render element tab when you have it open and thus the name of the element might appear wrong, re-open it to see it correct.
And as a final note, thanks to DenisT for suggesting a further optimization, just to prove you is always learning…. we can set the property for all the objects in our selection sets a bit simpler.
( re = maxOps.GetCurRenderElementMgr() for i = 1 to selectionsets.count do ( selectionsets[i].gbufferchannel = i re.addrenderelement (MatteRenderElement elementname:("Matte_" + i as string) gbufIDon:true gbbufID:i) ) )