<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Sketch render script in VRED Forum</title>
    <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12122219#M1102</link>
    <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4405096"&gt;@bryan_martin_morris&lt;/a&gt;, another small step...&lt;/P&gt;
&lt;P&gt;Managed the reuse of materials, sketched and switch, to avoid the creation of multiple and multiple materials&lt;/P&gt;
&lt;P&gt;Managed cloned nodes to avoid multiple unfolds&lt;/P&gt;
&lt;P&gt;Created 2 variantset to switch between realistic and scketched view&lt;/P&gt;
&lt;P&gt;Just 1 thing i miss, maybe&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/1842879"&gt;@seiferp&lt;/a&gt;&amp;nbsp;could help. i cannot find API to search and find material group folders in the material browser. so every time the procedure starts, one new group, maybe empty is created.&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import numpy as np
import cv2 as cv

# setting for the UV map size referred to how big is the selection
maxUVmapSize = 2048
coeffResolution = 2
pixelPadding = 10  #pixels
UVmapSavePath = 'c:/temp/UVMaps/'  
UseExistingMaps = False

def sketcherize(node_group):
    
    if not node_group:
        root_node = vrScenegraphService.getSelectedNode()
    else: 
        root_node = vrNodeService.findNode(node_group)
        
    # scan the model to find the geo and convert them to shell
    geo_nodes = [child for child in root_node.getChildrenRecursive() if child.isType(vrdGeometryNode)]
    for geo_node in geo_nodes:
        if not geo_node.isMesh():
            vrScenegraphService.convertToMesh([geo_node])
    nodes = [geo_node for geo_node in geo_nodes]
    # print(nodes)
    
    # try to find the biggest part to be used as a reference
    biggestNode = ""
    refMeasure = 0
    for node in nodes:
        bBox = node.getBoundingBox()
        bBoxSize = bBox.getSize()
        nodeRefMeasure = max([bBoxSize.x(), bBoxSize.y(), bBoxSize.z()])
        if nodeRefMeasure &amp;gt; refMeasure:
            refMeasure = nodeRefMeasure
            biggestNode = node.getName()
    print("Biggest Node: " + biggestNode + " - Reference Measure= " + str(refMeasure))
    
    # try to understand how big is the selection to compare with the UV map Max Size
    #bBox = root_node.getBoundingBox()
    #bBoxSize = bBox.getSize()
    # Search the max extents to use it as a reference
    #refMeasure = max([bBoxSize.x(), bBoxSize.y(), bBoxSize.z()])
    # calc a parameter to use to manage sizes for every shell
    if refMeasure == 0:
        refMeasure = 1000
    UVSizeCoeff = maxUVmapSize/refMeasure
    print("UVMapCoeff: " + str(UVSizeCoeff))
    
    # creation of the material Folder
    sketch_material_group_list = []
    sketch_material_group = vrMaterialService.createMaterialGroup()
    sketch_material_group.setName('sketch_material_group')
    
    # creation of the varianSet
    variantSetSketchName = "Sketcherized"
    variantSetRealName = "Realistic"
    vrVariantSets.deleteVariantSet(variantSetSketchName)
    vrVariantSets.deleteVariantSet(variantSetRealName)
    sketchVariant = vrVariantSets.createVariantSet(variantSetSketchName)
    realVariant = vrVariantSets.createVariantSet(variantSetRealName)
    sketchVariant.addScript('applySketchedView()')
    realVariant.addScript('applyrealisticView()')
    
    # base unfold settings
    layout_settings = vrdUVLayoutSettings()
    unfold_settings = vrdUVUnfoldSettings()
        
    # for each node...
    unfoldedNodes = []
    for node in nodes:
        curNodeName = node.getName()
        curNodeOId = node.getObjectId()
        if curNodeName.find("_#") &amp;lt; 0:
            node.setName(f'{node.getName()}_#{node.getObjectId()}')
        curNodeName = node.getName()
        
        # get the BBox to get the measures
        bBox1 = node.getBoundingBox()
        bBoxSize1 = bBox1.getSize()
        refMeasure1 = max([bBoxSize1.x(), bBoxSize1.y(), bBoxSize1.z()])
        nodeUVSize = refMeasure1 * UVSizeCoeff
        print(curNodeName + ": MaxBB = " + str(refMeasure1) + " - UvSize = " + str(nodeUVSize))
        
        map_size = nodeUVSize
        resolution = nodeUVSize/coeffResolution
        padding = pixelPadding
        padding /= map_size #UV 0.0-1
        
        layout_settings.setIslandPadding(padding)
        layout_settings.setTilePadding(padding)
        layout_settings.setResolution(resolution)
        unfold_settings.setMapSize(map_size)
        
        isToUnfold = True        
        if UseExistingMaps and node.hasUVSet(vrUVTypes.UVSet.MaterialUVSet):
            isToUnfold = False
        if isToUnfold:
            # check if it was already unfolded
            if curNodeName in unfoldedNodes:
                print("Skipped Unfold. Node already Unfolded: " + curNodeName)
            else:
                print("Unfolding " + curNodeName)
                vrUVService.unfold([node], unfold_settings, layout_settings, vrUVTypes.UVSet.MaterialUVSet)
                # insert in a list the unfolded nodes, to avoid to unfold many times the cloned nodes
                unfoldedNodes.append(curNodeName)
            
        uv_path=f'{UVmapSavePath}{curNodeName}.png'
        vrUVService.saveUVSnapshot(
                        [node], 
                        uv_path,
                        map_size,map_size,
                        vrUVTypes.UVSet.MaterialUVSet,
                        vrUVTypes.ShowBorders)

        # read image into openCV
        image = cv.imread(uv_path)
        # convert img to grayscale
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        # make anything not white into black
        mask = gray.copy()
        mask[mask!=0] = 255        
        # do this...
        kernel = np.ones((5,5),np.uint8)        
        # grow the mask (1 times but can be reduced/increased depending on the requirements).
        dilate = cv.dilate(mask, kernel, iterations=1)
        # invert to black on white
        inverted = cv.bitwise_not(dilate)
        # overwrite the original
        cv.imwrite(uv_path, inverted)
        
        # create the material and the switch
        old_mat = node.getMaterial()
        newMatName = curNodeName + '_sketchUV'
        new_mat = vrMaterialService.findMaterial(newMatName)
        if new_mat and new_mat.isValid():
            print("Meterial " + newMatName + " Found.")
        else:
            new_mat = vrMaterialService.createMaterial(newMatName, vrMaterialTypes.MaterialType.Plastic, sketch_material_group)
            print("Meterial " + newMatName + " Created.")
        sketch_texture = vrImageService.loadImage(uv_path)
        dif_texture = new_mat.getDiffuseTexture()
        dif_color = QVector3D(1.,1.,1.)
        new_mat.setDiffuseColor(dif_color)
        
        dif_texture.setImage(sketch_texture)
        dif_texture.setUseTexture(True)
        dif_texture.setUseAlpha(False)
        dif_texture.setMappingType(vrTextureTypes.MappingType.UVMapping)
        
        matSwitchName = curNodeName + '_sketchUV_material_switch'
        mat_switch = vrMaterialService.findMaterial(matSwitchName)
        if mat_switch and mat_switch.isValid():
            print("material Switch " + matSwitchName + " Found.")
        else:
            mat_switch = vrMaterialService.createSwitchMaterial([new_mat, old_mat], sketch_material_group)
            mat_switch.setName(matSwitchName)
            print("material Switch " + matSwitchName + " Created.")        
        node.applyMaterial(mat_switch)
        
# sketcherize(None)

def applySketchedView():
    print("Sketched VariantSet")
    root_node = vrScenegraphService.getSelectedNode()
    nodes = [child for child in root_node.getChildrenRecursive()]
    for node in nodes:
        curMat = node.getMaterial()
        if curMat and curMat.isValid() and curMat.isType(vrdSwitchMaterial):
            #print(node.getName() + " - " + curMat.getName() + " - " + str(curMat.isType(vrdSwitchMaterial)))
            curMat.setChoice(0)
    print("Sketched VariantSet Applied")
    
def applyrealisticView():
    print("Realistic VariantSet")
    root_node = vrScenegraphService.getSelectedNode()
    nodes = [child for child in root_node.getChildrenRecursive()]
    for node in nodes:
        curMat = node.getMaterial()
        if curMat and curMat.isValid() and curMat.isType(vrdSwitchMaterial):
            #print(node.getName() + " - " + curMat.getName() + " - " + str(curMat.isType(vrdSwitchMaterial)))
            curMat.setChoice(1)
    print("Realistic VariantSet Applied")&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;best&lt;/P&gt;
&lt;P&gt;Chris&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 24 Jul 2023 13:38:22 GMT</pubDate>
    <dc:creator>Christian_Garimberti</dc:creator>
    <dc:date>2023-07-24T13:38:22Z</dc:date>
    <item>
      <title>Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12097073#M1096</link>
      <description>&lt;P&gt;Hi all,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Not sure this is of interest for anyone, considering that usually VRED is intended to make things look photo real. But&amp;nbsp; I have been in need of a one stop solution to doing some renders/videos that have a technical drawing aesthetic, that can be easily mapped over or below photo real renders with appropriately visible details.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To do so I have made a quite poor but somewhat functional script.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;It essentially recreates the style of the non-realistic renderer, but you can ray-trace the result. It requires opencv-python and numpy to be installed.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I convert NURBS to mesh (and rename them as otherwise bad things happen), then use the UV editor to make a snapshot, then modify the image to black lines, thicken them, and then UV map the result. I also make material switches so that the effect can be switched using another script... but this makes a mess of the material editor, as it makes a material, and switch per part...!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I don't think it's very efficient, and the results can be a bit hit and miss (some parts seem to require multiple dilate iterations... see the cab and hydraulics).&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="digger.png" style="width: 600px;"&gt;&lt;img src="https://forums.autodesk.com/t5/image/serverpage/image-id/1239589i5F33979D361657F2/image-size/medium?v=v2&amp;amp;px=400" role="button" title="digger.png" alt="digger.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;But I think the result kind of cool, and roughly works for what I want it to... It just takes an age to do more complex models, with the UV editor throwing some errors, and VRED becoming unresponsive for a while (It took roughly 4 minutes for the digger).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;No idea if its useful to anyone, but if so... great. If anyone has any ideas for an approach that could do this more efficiently, I'd be interested.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Cheers.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;import numpy as np
import cv2 as cv

def sketcherize(node_group):

    root_node = vrNodeService.findNode(node_group)
    
    geo_nodes = [child for child in root_node.getChildrenRecursive() if child.isType(vrdGeometryNode)]

    nodes = [geo_node for geo_node in geo_nodes if geo_node.isShell()]
    
    for node in nodes:
        if not node.isMesh():
            vrScenegraphService.convertToMesh([node]) 
    
    map_size = 2056
    resolution = 1024
    padding = 10 #pixels
    padding /= map_size #UV 0.0-1
    
    save_path = 'YOUR PATH GOES HERE :)'  

    layout_settings = vrdUVLayoutSettings()
    layout_settings.setIslandPadding(padding)
    layout_settings.setTilePadding(padding)
    layout_settings.setResolution(resolution)
        
    unfold_settings = vrdUVUnfoldSettings()
    unfold_settings.setMapSize(map_size)
    
    vrUVService.unfold(nodes, unfold_settings, layout_settings, vrUVTypes.UVSet.MaterialUVSet)
    
    sketch_material_group_list = [] 
    sketch_material_group = vrMaterialService.createMaterialGroup()
    sketch_material_group.setName('sketch_material_group')
    
    for node in nodes:
        node.setName(f'{node.getName()}_{node.getObjectId()}')

        uv_path=f'{save_path}{node.getName()}.png'
        vrUVService.saveUVSnapshot(
                        [node], 
                        uv_path,
                        2056,2056,
                        vrUVTypes.UVSet.MaterialUVSet,
                        vrUVTypes.ShowBorders)
        # read image into openCV
        image = cv.imread(uv_path)

        # convert img to grayscale
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

        # make anything not white into black
        mask = gray.copy()
        mask[mask!=0] = 255        
        
        # do this...
        kernel = np.ones((5,5),np.uint8)
        
        # grow the mask (1 times but can be reduced/increased depending on the requirements).
        dilate = cv.dilate(mask, kernel, iterations=1)
                
        # invert to black on white
        inverted = cv.bitwise_not(dilate)
        
        # overwrite the original
        cv.imwrite(uv_path, inverted)
        
        old_mat = node.getMaterial()
        new_mat = vrMaterialService.createMaterial(
            f'{node.getName()}_sketchUV',
            vrMaterialTypes.MaterialType.Plastic,
            sketch_material_group)
        sketch_texture = vrImageService.loadImage(uv_path)
        dif_texture = new_mat.getDiffuseTexture()
        dif_color = QVector3D(1.,1.,1.)
        new_mat.setDiffuseColor(dif_color)
        
        dif_texture.setImage(sketch_texture)
        dif_texture.setUseTexture(True)
        dif_texture.setUseAlpha(False)
        dif_texture.setMappingType(vrTextureTypes.MappingType.UVMapping)
        
        
        mat_switch = vrMaterialService.createSwitchMaterial([new_mat,old_mat],sketch_material_group)
        mat_switch.setName(f'{node.getName()}_sketchUV_material_switch')
        
        node.applyMaterial(mat_switch)&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 12 Jul 2023 15:50:42 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12097073#M1096</guid>
      <dc:creator>bryan_martin_morris</dc:creator>
      <dc:date>2023-07-12T15:50:42Z</dc:date>
    </item>
    <item>
      <title>Re: Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12098643#M1097</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4405096"&gt;@bryan_martin_morris&lt;/a&gt;&amp;nbsp;i will take a look at your script! it seems to be a very useful thing thinking about industrial staff that not alwaysneed a "real" render.&lt;/P&gt;
&lt;P&gt;And if i'll find some improvements i will send it you back&lt;/P&gt;
&lt;P&gt;Thank you for sharing!&lt;/P&gt;
&lt;P&gt;Chris&lt;/P&gt;</description>
      <pubDate>Thu, 13 Jul 2023 07:31:43 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12098643#M1097</guid>
      <dc:creator>Christian_Garimberti</dc:creator>
      <dc:date>2023-07-13T07:31:43Z</dc:date>
    </item>
    <item>
      <title>Re: Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12108569#M1098</link>
      <description>&lt;P&gt;well this look pretty cool.&lt;/P&gt;&lt;P&gt;making such renders, even in the NPR mode, is always a pain.&lt;/P&gt;</description>
      <pubDate>Tue, 18 Jul 2023 06:42:09 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12108569#M1098</guid>
      <dc:creator>cikho</dc:creator>
      <dc:date>2023-07-18T06:42:09Z</dc:date>
    </item>
    <item>
      <title>Re: Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12109713#M1099</link>
      <description>&lt;P&gt;Hi &lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4405096"&gt;@bryan_martin_morris&lt;/a&gt;&amp;nbsp;, this is my first upgrade to your script.&lt;/P&gt;
&lt;P&gt;I managed part dimensions to pilot maps dimension, so more or less every part have the same "line" resolution.&lt;/P&gt;
&lt;P&gt;Maybe it is not faster but slower, since i had to unfold every single part and scan the whole model to find the biggest part as a reference.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Christian_Garimberti_0-1689694891699.png" style="width: 600px;"&gt;&lt;img src="https://forums.autodesk.com/t5/image/serverpage/image-id/1241925iE5B21963B2099534/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Christian_Garimberti_0-1689694891699.png" alt="Christian_Garimberti_0-1689694891699.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I added an options to reuse the existing uvmaps if there are.&lt;/P&gt;
&lt;P&gt;Let me know.&lt;/P&gt;
&lt;P&gt;Best&lt;/P&gt;
&lt;P&gt;Chris&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import numpy as np
import cv2 as cv

# setting for the UV map size referred to how big is the selection
maxUVmapSize = 2048
coeffResolution = 2
pixelPadding = 10  #pixels
UVmapSavePath = 'c:/temp/UVMaps/'  
UseExistingMaps = False

def sketcherize(node_group):
    
    if not node_group:
        root_node = vrScenegraphService.getSelectedNode()
    else: 
        root_node = vrNodeService.findNode(node_group)
        
    # scan the model to find the geo and convert them to shell
    geo_nodes = [child for child in root_node.getChildrenRecursive() if child.isType(vrdGeometryNode)]
    for geo_node in geo_nodes:
        if not geo_node.isMesh():
            vrScenegraphService.convertToMesh([geo_node])
    nodes = [geo_node for geo_node in geo_nodes]
    # print(nodes)
    
    # try to find the biggest part to be used as a reference
    biggestNode = ""
    refMeasure = 0
    for node in nodes:
        bBox = node.getBoundingBox()
        bBoxSize = bBox.getSize()
        nodeRefMeasure = max([bBoxSize.x(), bBoxSize.y(), bBoxSize.z()])
        if nodeRefMeasure &amp;gt; refMeasure:
            refMeasure = nodeRefMeasure
            biggestNode = node.getName()
    print("Biggest Node: " + biggestNode + " - Reference Measure= " + str(refMeasure))
    
    # try to understand how big is the selection to compare with the UV map Max Size
    #bBox = root_node.getBoundingBox()
    #bBoxSize = bBox.getSize()
    # Search the max extents to use it as a reference
    #refMeasure = max([bBoxSize.x(), bBoxSize.y(), bBoxSize.z()])
    # calc a parameter to use to manage sizes for every shell
    if refMeasure == 0:
        refMeasure = 1000
    UVSizeCoeff = maxUVmapSize/refMeasure
    print("UVMapCoeff: " + str(UVSizeCoeff))
    
    sketch_material_group_list = []
    sketch_material_group = vrMaterialService.createMaterialGroup()
    sketch_material_group.setName('sketch_material_group')
    
    layout_settings = vrdUVLayoutSettings()
    unfold_settings = vrdUVUnfoldSettings()
    
    for node in nodes:
        curNodeName = node.getName()
        curNodeOId = node.getObjectId()
        if curNodeName.find("_" + str(curNodeOId)) &amp;lt; 0:
            node.setName(f'{node.getName()}_{node.getObjectId()}')
        curNodeName = node.getName()
        
        # get the BBox to get the measures
        bBox1 = node.getBoundingBox()
        bBoxSize1 = bBox1.getSize()
        refMeasure1 = max([bBoxSize1.x(), bBoxSize1.y(), bBoxSize1.z()])
        nodeUVSize = refMeasure1 * UVSizeCoeff
        print(curNodeName + ": MaxBB = " + str(refMeasure1) + " - UvSize = " + str(nodeUVSize))
        
        map_size = nodeUVSize
        resolution = nodeUVSize/coeffResolution
        padding = pixelPadding
        padding /= map_size #UV 0.0-1
        
        
        layout_settings.setIslandPadding(padding)
        layout_settings.setTilePadding(padding)
        layout_settings.setResolution(resolution)
        unfold_settings.setMapSize(map_size)
        
        isToUnfold = True
        if UseExistingMaps and node.hasUVSet(vrUVTypes.UVSet.MaterialUVSet):
            isToUnfold = False
        if isToUnfold:
            print("Unfolding " + curNodeName)
            vrUVService.unfold([node], unfold_settings, layout_settings, vrUVTypes.UVSet.MaterialUVSet)

        uv_path=f'{UVmapSavePath}{curNodeName}.png'
        vrUVService.saveUVSnapshot(
                        [node], 
                        uv_path,
                        map_size,map_size,
                        vrUVTypes.UVSet.MaterialUVSet,
                        vrUVTypes.ShowBorders)
        # read image into openCV
        image = cv.imread(uv_path)

        # convert img to grayscale
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

        # make anything not white into black
        mask = gray.copy()
        mask[mask!=0] = 255        
        
        # do this...
        kernel = np.ones((5,5),np.uint8)
        
        # grow the mask (1 times but can be reduced/increased depending on the requirements).
        dilate = cv.dilate(mask, kernel, iterations=1)
                
        # invert to black on white
        inverted = cv.bitwise_not(dilate)
        
        # overwrite the original
        cv.imwrite(uv_path, inverted)
        
        old_mat = node.getMaterial()
        new_mat = vrMaterialService.createMaterial(
            f'{node.getName()}_sketchUV',
            vrMaterialTypes.MaterialType.Plastic,
            sketch_material_group)
        sketch_texture = vrImageService.loadImage(uv_path)
        dif_texture = new_mat.getDiffuseTexture()
        dif_color = QVector3D(1.,1.,1.)
        new_mat.setDiffuseColor(dif_color)
        
        dif_texture.setImage(sketch_texture)
        dif_texture.setUseTexture(True)
        dif_texture.setUseAlpha(False)
        dif_texture.setMappingType(vrTextureTypes.MappingType.UVMapping)
        
        
        mat_switch = vrMaterialService.createSwitchMaterial([new_mat,old_mat],sketch_material_group)
        mat_switch.setName(f'{node.getName()}_sketchUV_material_switch')
        
        node.applyMaterial(mat_switch)
        
# sketcherize(None)&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 18 Jul 2023 15:42:59 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12109713#M1099</guid>
      <dc:creator>Christian_Garimberti</dc:creator>
      <dc:date>2023-07-18T15:42:59Z</dc:date>
    </item>
    <item>
      <title>Re: Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12109734#M1100</link>
      <description>&lt;P&gt;Cool stuff you are doing there&amp;nbsp;&lt;span class="lia-unicode-emoji" title=":victory_hand:"&gt;✌️&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 18 Jul 2023 15:50:16 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12109734#M1100</guid>
      <dc:creator>seiferp</dc:creator>
      <dc:date>2023-07-18T15:50:16Z</dc:date>
    </item>
    <item>
      <title>Re: Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12111720#M1101</link>
      <description>&lt;P&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/1273567"&gt;@Christian_Garimberti&lt;/a&gt;&amp;nbsp;I like the plan to compare sizes and then even out the line weights &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt; . I'll give it a go on my home workstation as soon as I get a chance.&lt;/P&gt;&lt;P&gt;I'm not convinced my choice of opencv is the best solution for the image work, I just used it as I have some other half-finished projects where it was useful. The reason I wonder is that I think the image files could probably benefit from some anti-aliasing but I guess robots and computers don't have much use for anti-aliased images.&lt;/P&gt;</description>
      <pubDate>Wed, 19 Jul 2023 11:44:52 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12111720#M1101</guid>
      <dc:creator>bryan_martin_morris</dc:creator>
      <dc:date>2023-07-19T11:44:52Z</dc:date>
    </item>
    <item>
      <title>Re: Sketch render script</title>
      <link>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12122219#M1102</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/4405096"&gt;@bryan_martin_morris&lt;/a&gt;, another small step...&lt;/P&gt;
&lt;P&gt;Managed the reuse of materials, sketched and switch, to avoid the creation of multiple and multiple materials&lt;/P&gt;
&lt;P&gt;Managed cloned nodes to avoid multiple unfolds&lt;/P&gt;
&lt;P&gt;Created 2 variantset to switch between realistic and scketched view&lt;/P&gt;
&lt;P&gt;Just 1 thing i miss, maybe&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/1842879"&gt;@seiferp&lt;/a&gt;&amp;nbsp;could help. i cannot find API to search and find material group folders in the material browser. so every time the procedure starts, one new group, maybe empty is created.&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;import numpy as np
import cv2 as cv

# setting for the UV map size referred to how big is the selection
maxUVmapSize = 2048
coeffResolution = 2
pixelPadding = 10  #pixels
UVmapSavePath = 'c:/temp/UVMaps/'  
UseExistingMaps = False

def sketcherize(node_group):
    
    if not node_group:
        root_node = vrScenegraphService.getSelectedNode()
    else: 
        root_node = vrNodeService.findNode(node_group)
        
    # scan the model to find the geo and convert them to shell
    geo_nodes = [child for child in root_node.getChildrenRecursive() if child.isType(vrdGeometryNode)]
    for geo_node in geo_nodes:
        if not geo_node.isMesh():
            vrScenegraphService.convertToMesh([geo_node])
    nodes = [geo_node for geo_node in geo_nodes]
    # print(nodes)
    
    # try to find the biggest part to be used as a reference
    biggestNode = ""
    refMeasure = 0
    for node in nodes:
        bBox = node.getBoundingBox()
        bBoxSize = bBox.getSize()
        nodeRefMeasure = max([bBoxSize.x(), bBoxSize.y(), bBoxSize.z()])
        if nodeRefMeasure &amp;gt; refMeasure:
            refMeasure = nodeRefMeasure
            biggestNode = node.getName()
    print("Biggest Node: " + biggestNode + " - Reference Measure= " + str(refMeasure))
    
    # try to understand how big is the selection to compare with the UV map Max Size
    #bBox = root_node.getBoundingBox()
    #bBoxSize = bBox.getSize()
    # Search the max extents to use it as a reference
    #refMeasure = max([bBoxSize.x(), bBoxSize.y(), bBoxSize.z()])
    # calc a parameter to use to manage sizes for every shell
    if refMeasure == 0:
        refMeasure = 1000
    UVSizeCoeff = maxUVmapSize/refMeasure
    print("UVMapCoeff: " + str(UVSizeCoeff))
    
    # creation of the material Folder
    sketch_material_group_list = []
    sketch_material_group = vrMaterialService.createMaterialGroup()
    sketch_material_group.setName('sketch_material_group')
    
    # creation of the varianSet
    variantSetSketchName = "Sketcherized"
    variantSetRealName = "Realistic"
    vrVariantSets.deleteVariantSet(variantSetSketchName)
    vrVariantSets.deleteVariantSet(variantSetRealName)
    sketchVariant = vrVariantSets.createVariantSet(variantSetSketchName)
    realVariant = vrVariantSets.createVariantSet(variantSetRealName)
    sketchVariant.addScript('applySketchedView()')
    realVariant.addScript('applyrealisticView()')
    
    # base unfold settings
    layout_settings = vrdUVLayoutSettings()
    unfold_settings = vrdUVUnfoldSettings()
        
    # for each node...
    unfoldedNodes = []
    for node in nodes:
        curNodeName = node.getName()
        curNodeOId = node.getObjectId()
        if curNodeName.find("_#") &amp;lt; 0:
            node.setName(f'{node.getName()}_#{node.getObjectId()}')
        curNodeName = node.getName()
        
        # get the BBox to get the measures
        bBox1 = node.getBoundingBox()
        bBoxSize1 = bBox1.getSize()
        refMeasure1 = max([bBoxSize1.x(), bBoxSize1.y(), bBoxSize1.z()])
        nodeUVSize = refMeasure1 * UVSizeCoeff
        print(curNodeName + ": MaxBB = " + str(refMeasure1) + " - UvSize = " + str(nodeUVSize))
        
        map_size = nodeUVSize
        resolution = nodeUVSize/coeffResolution
        padding = pixelPadding
        padding /= map_size #UV 0.0-1
        
        layout_settings.setIslandPadding(padding)
        layout_settings.setTilePadding(padding)
        layout_settings.setResolution(resolution)
        unfold_settings.setMapSize(map_size)
        
        isToUnfold = True        
        if UseExistingMaps and node.hasUVSet(vrUVTypes.UVSet.MaterialUVSet):
            isToUnfold = False
        if isToUnfold:
            # check if it was already unfolded
            if curNodeName in unfoldedNodes:
                print("Skipped Unfold. Node already Unfolded: " + curNodeName)
            else:
                print("Unfolding " + curNodeName)
                vrUVService.unfold([node], unfold_settings, layout_settings, vrUVTypes.UVSet.MaterialUVSet)
                # insert in a list the unfolded nodes, to avoid to unfold many times the cloned nodes
                unfoldedNodes.append(curNodeName)
            
        uv_path=f'{UVmapSavePath}{curNodeName}.png'
        vrUVService.saveUVSnapshot(
                        [node], 
                        uv_path,
                        map_size,map_size,
                        vrUVTypes.UVSet.MaterialUVSet,
                        vrUVTypes.ShowBorders)

        # read image into openCV
        image = cv.imread(uv_path)
        # convert img to grayscale
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        # make anything not white into black
        mask = gray.copy()
        mask[mask!=0] = 255        
        # do this...
        kernel = np.ones((5,5),np.uint8)        
        # grow the mask (1 times but can be reduced/increased depending on the requirements).
        dilate = cv.dilate(mask, kernel, iterations=1)
        # invert to black on white
        inverted = cv.bitwise_not(dilate)
        # overwrite the original
        cv.imwrite(uv_path, inverted)
        
        # create the material and the switch
        old_mat = node.getMaterial()
        newMatName = curNodeName + '_sketchUV'
        new_mat = vrMaterialService.findMaterial(newMatName)
        if new_mat and new_mat.isValid():
            print("Meterial " + newMatName + " Found.")
        else:
            new_mat = vrMaterialService.createMaterial(newMatName, vrMaterialTypes.MaterialType.Plastic, sketch_material_group)
            print("Meterial " + newMatName + " Created.")
        sketch_texture = vrImageService.loadImage(uv_path)
        dif_texture = new_mat.getDiffuseTexture()
        dif_color = QVector3D(1.,1.,1.)
        new_mat.setDiffuseColor(dif_color)
        
        dif_texture.setImage(sketch_texture)
        dif_texture.setUseTexture(True)
        dif_texture.setUseAlpha(False)
        dif_texture.setMappingType(vrTextureTypes.MappingType.UVMapping)
        
        matSwitchName = curNodeName + '_sketchUV_material_switch'
        mat_switch = vrMaterialService.findMaterial(matSwitchName)
        if mat_switch and mat_switch.isValid():
            print("material Switch " + matSwitchName + " Found.")
        else:
            mat_switch = vrMaterialService.createSwitchMaterial([new_mat, old_mat], sketch_material_group)
            mat_switch.setName(matSwitchName)
            print("material Switch " + matSwitchName + " Created.")        
        node.applyMaterial(mat_switch)
        
# sketcherize(None)

def applySketchedView():
    print("Sketched VariantSet")
    root_node = vrScenegraphService.getSelectedNode()
    nodes = [child for child in root_node.getChildrenRecursive()]
    for node in nodes:
        curMat = node.getMaterial()
        if curMat and curMat.isValid() and curMat.isType(vrdSwitchMaterial):
            #print(node.getName() + " - " + curMat.getName() + " - " + str(curMat.isType(vrdSwitchMaterial)))
            curMat.setChoice(0)
    print("Sketched VariantSet Applied")
    
def applyrealisticView():
    print("Realistic VariantSet")
    root_node = vrScenegraphService.getSelectedNode()
    nodes = [child for child in root_node.getChildrenRecursive()]
    for node in nodes:
        curMat = node.getMaterial()
        if curMat and curMat.isValid() and curMat.isType(vrdSwitchMaterial):
            #print(node.getName() + " - " + curMat.getName() + " - " + str(curMat.isType(vrdSwitchMaterial)))
            curMat.setChoice(1)
    print("Realistic VariantSet Applied")&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;best&lt;/P&gt;
&lt;P&gt;Chris&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 24 Jul 2023 13:38:22 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/vred-forum/sketch-render-script/m-p/12122219#M1102</guid>
      <dc:creator>Christian_Garimberti</dc:creator>
      <dc:date>2023-07-24T13:38:22Z</dc:date>
    </item>
  </channel>
</rss>

