Announcement

Collapse
No announcement yet.

Script - Create a MultiMatte by layer

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Script - Create a MultiMatte by layer

    If you don't have VRayScatter or MultiScatter and a massively huge scene, you probably won't get the same errors... But you may find the script useful if you use layers extensively.

    It runs through the list of layers and gives a unique .gbufferchannel to all objects on each layer. Then generates one MultiMatte per three layers. Until I build a UI, it simply starts at ObjectID 300.

    Layer01 objects are assigned gbufferchannel 301
    Layer02 objects 302
    Layer03 objects 303
    Layer04 objects 304
    Layer05 objects 305
    Layer06 objects 306
    etc
    MultiMatte "Layer01Layer02Layer03" is 301 for Red, 302 for Green, 303 for Blue

    etc, etc, through all layers.

    It also truncates layers so that the MultiMatte name is <= 31 characters due to the EXR spec for channel names, but that's irrelevant.

    It gets the nodes on each layer using refs.dependents for each layer and then filtering out only the GeometryClass nodes. This works fine on small scenes but for some reason on my current scene with nearly 11,000 objects, it is breaking.

    Check the listener to get an idea of what it's doing.

    Here is an example of the layerRefs vs the filtered nodes:

    layerRefs: #($VRS_GreenRoof_OrnimentalGrass01, ReferenceTarget:NodeSelection, ReferenceTarget:ReferenceTarget, ReferenceTarget:ReferenceTarget, ReferenceTarget:NodeSelection, ReferenceTarget:ParamBlock2, RMVisSetArray2:RMVisSetArray2, Controller:Bezier_Float, ReferenceTarget:ParamBlock2, RMVisSetArray1:RMVisSetArray1, $VRS_GreenRoof_MiscanthusClump02, $VRS_GreenRoof_Fescue02, $VRS_SucculentGarden_Base, ReferenceTarget:NodeNamedSelSet, ReferenceTarget:NamedSelSetList, ReferenceTarget:Scene, ReferenceTarget:ParamBlock2, VRayScatter, ReferenceTarget:ParamBlock2, VRayScatter, ...)

    layerNodes: #($VRS_GreenRoof_OrnimentalGrass01, $VRS_GreenRoof_MiscanthusClump02, $VRS_GreenRoof_Fescue02, $VRS_SucculentGarden_Base, VRayScatter, VRayScatter, VRayScatter)
    The problem is with the highlighted VRayScatter objects. The $VRS_... objects are VRayScatter class as well but show up properly in the node array...

    It works fine a small test scene. It cycles through all layers even with VRayScatter objects and has no problem....

    sigh

    Code:
    clearlistener()
    
    fn keepChars str pass: = (
        local killChars  = case pass of
        (
            1: "abcdefghijklmnopqrstuvwxyz0123456_" 
            2: "abcdefghijklmnopqrstuvwxyz"
            3: "bcdfghjklmnpqrstvwxyz"
        )
        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 %\n\n" elName
                re.REmoveRenderElement x
            )
        )
        
    )
    
    
    
    (
        local re = maxOps.GetCurRenderElementMgr() 
        local el = multimatteelement
        local groupsSoFar = 0 
        local startID = 300
        
        removeElementByPrefix "LAY_"
        
        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 obj = 1 to layerNodes.count do
                (
                    if layerNodes[obj] != "VRayScatter" do 
                    (
                        layerNodes[obj].gbufferChannel = x
                    )
                    
                )
                format "LayerRefs: %\n" layerRefs
                format "Layer: %\n" layerName
                format "Objects: %\n" layerNodes
                format "ObjectID: %\n" x
            )
            
            if idGroup.count < 3 do
            (
                append idGroup (idGroup[idGroup.count] + 1)
                if idGroup.count < 3 then 
                (
                    append idGroup (idGroup[idGroup.count] + 1)
                )
                else()
            )
    
            layerGroup = "LAY_" + layerGroup
            format "MultiMatte name: % is % characters.\n" layerGroup  layerGroup.count
            format "IDs in MM: %\n\n" idGroup
            format "--------------------\n\n"
    
            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
        )    
    )
    Any help would be primo,

    Also posted on CGTalk I hope that's not a forum faux pas
Working...
X