<?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: USDZ not including textures using typical export workflow in 3ds Max Forum</title>
    <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074938#M1871</link>
    <description>&lt;P&gt;The export for the last few versions uses USD Shade NodeGraphs (&lt;A href="https://openusd.org/dev/api/class_usd_shade_node_graph.html" target="_blank" rel="noopener"&gt;https://openusd.org/dev/api/class_usd_shade_node_graph.html&lt;/A&gt;), so to comply with UsdShade connection rules. I dont think this is well supported in the iOS viewers - which unless I am mistaken, support the "arkit" spec. "arkit"&amp;nbsp; only supports a subset of USD features. When we export to USDZ, we do not comply with this subset of the USD spec.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Unreal similarly lacks support for USD NodeGraphs, and I had written a little chaser plugin for someone else to bypass the usage of NodeGraphs (see bellow).&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;After running this script, you will have the option to enable this chasers in the exporter UI like so :&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="juliendeboise_0-1728504317260.png" style="width: 600px;"&gt;&lt;img src="https://forums.autodesk.com/t5/image/serverpage/image-id/1419728i21021C8686BBAADE/image-size/medium?v=v2&amp;amp;px=400" role="button" title="juliendeboise_0-1728504317260.png" alt="juliendeboise_0-1728504317260.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What this chaser (a chaser is just some code that runs after the export to post-process the resulting usd stage) does is bypass the nodegraphs by connecting the materials directly onto the texture nodes. This violates some usd shade connection rules - but these are very rarely enforced and it might work for you (disclaimer : have only tried this for unreal, only suspect the issue is the same).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As I said though, the ARKIT USD spec is a small subset of what is supported in USD and so many other things may not work.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="general"&gt;import maxUsd
from pxr import Usd
from pxr import UsdShade
from pymxs import runtime as mxs

import os, sys, glob

class matFixChaser(maxUsd.ExportChaser):

    def __init__(self, factoryContext, *args, **kwargs):
        super(matFixChaser, self).__init__(factoryContext, *args, **kwargs)
        self.stage = factoryContext.GetStage()

    def isId(self, id , shader):
        info_id_attr = shader.GetIdAttr()
        if info_id_attr:
            id_value = info_id_attr.Get()
            return id_value == id
        return False

    def PostExport(self):
        try:
            print("Running Unreal UsdPreviewSurface fix chaser...")
            
            all_shaders = [x for x in self.stage.Traverse() if UsdShade.Shader(x)]
            for prim in all_shaders:
                
                shader = UsdShade.Shader(prim)                
                if self.isId('UsdPreviewSurface', shader):
                    
                     # Iterate over the shader's inputs
                    for input in shader.GetInputs():
                        # Check if the input is connected
                        if input.HasConnectedSource():
                            # Get the connected path
                            source = input.GetConnectedSource()
                            source_prim = source[0].GetPrim()
                            
                            # The node graph connection...
                            connection_path = source_prim.GetPath()
                            # print(connection_path)
                            
                            # Instead connect to the USD texture 2d that lives inside the node graph.
                            new_connection = connection_path.AppendChild(source_prim.GetName())
                            # print(new_connection)
                            
                            texture = UsdShade.Shader(self.stage.GetPrimAtPath(new_connection))
                            input.ConnectToSource(texture.ConnectableAPI(), 'rgb')
                            
                            
                    continue
                if self.isId('UsdPrimvarReader_float2', shader):                    
                    varname_input = shader.GetInput("varname")
                    varname_value_attributes = varname_input.GetValueProducingAttributes()
                    primvar_name = varname_value_attributes[0].Get()
                    # Punch in value directly, not from nodegraph...
                    varname_input.Set(primvar_name)
                                        
                            
        except Exception as e:
            print('Chaser ERROR : %s' % str(e))
            print(traceback.format_exc())
        
        return True

        
maxUsd.ExportChaser.Register(matFixChaser, "unrealMatFixer", "Unreal UsdPreviewSurface fix chaser", "Connects straight to textures, bypassing nodegraphs.")


def unrealMatFixContext():
    extraArgs = {}    
    extraArgs['chaser']  = ['unrealMatFixer']
    extraArgs['chaserNames']  = ['unrealMatFixer']
    return extraArgs

registeredContexts = maxUsd.JobContextRegistry.ListJobContexts()
if 'unrealMatFixContext' not in registeredContexts:
    maxUsd.JobContextRegistry.RegisterExportJobContext("unrealMatFixContext", "Fix USD Preview Surface for Unreal", "Fixes USD preview surface materials for usage in Unreal, avoiding NodeGraphs.", unrealMatFixContext)

print("Registered unreal material fixer")&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 09 Oct 2024 20:17:15 GMT</pubDate>
    <dc:creator>julien.deboise</dc:creator>
    <dc:date>2024-10-09T20:17:15Z</dc:date>
    <item>
      <title>USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074420#M1868</link>
      <description>&lt;P&gt;I can't seem to get textures to go along with my USDZ exports now. I've done this a dozen times in 3dsmax 2023 with the previous USDZ exporter, but with 2024 and the lastest USD plugin, I just can't get textures on my objects to save. I opened an older scene that has exported fine in the past and re-exported with the new setup and textures didn't show. Does anybody know what I'm doing wrong? I have an image attached of a setup that doesn't export properly. I brought the USDZ into Blender to test it too (thinking maybe it was just my phone being the issue) but Blender showed no texture on it too.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 09 Oct 2024 15:33:51 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074420#M1868</guid>
      <dc:creator>ian3GB9G</dc:creator>
      <dc:date>2024-10-09T15:33:51Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074606#M1869</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Could you enable Logging in the USD Exporter. And set the Output to Error and warnings and share the output?&lt;/P&gt;</description>
      <pubDate>Wed, 09 Oct 2024 17:16:14 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074606#M1869</guid>
      <dc:creator>Max.macmillan</dc:creator>
      <dc:date>2024-10-09T17:16:14Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074855#M1870</link>
      <description>&lt;P&gt;Unfortunately USD in Max is not as robust and viable as we would all like it to be. Each time I dive in and decide to learn USD, NVidia Composer, etc., I’m met with all kinds of functionality issues. In Max 2023 I can’t export a Tycache but in Max 2025 I can. USD is awesome, but from my perspective, it’s still incomplete and Beta. I waste a couple of days every month trying to get it to work well and am so far always disappointed and just drop it till the next month. I hope that a year from now I’ll be cranking a long with no issues.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So it may not be you, it just may be that USD is just not up to speed yet.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 09 Oct 2024 19:23:10 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074855#M1870</guid>
      <dc:creator>RobH2</dc:creator>
      <dc:date>2024-10-09T19:23:10Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074938#M1871</link>
      <description>&lt;P&gt;The export for the last few versions uses USD Shade NodeGraphs (&lt;A href="https://openusd.org/dev/api/class_usd_shade_node_graph.html" target="_blank" rel="noopener"&gt;https://openusd.org/dev/api/class_usd_shade_node_graph.html&lt;/A&gt;), so to comply with UsdShade connection rules. I dont think this is well supported in the iOS viewers - which unless I am mistaken, support the "arkit" spec. "arkit"&amp;nbsp; only supports a subset of USD features. When we export to USDZ, we do not comply with this subset of the USD spec.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Unreal similarly lacks support for USD NodeGraphs, and I had written a little chaser plugin for someone else to bypass the usage of NodeGraphs (see bellow).&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;After running this script, you will have the option to enable this chasers in the exporter UI like so :&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="juliendeboise_0-1728504317260.png" style="width: 600px;"&gt;&lt;img src="https://forums.autodesk.com/t5/image/serverpage/image-id/1419728i21021C8686BBAADE/image-size/medium?v=v2&amp;amp;px=400" role="button" title="juliendeboise_0-1728504317260.png" alt="juliendeboise_0-1728504317260.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What this chaser (a chaser is just some code that runs after the export to post-process the resulting usd stage) does is bypass the nodegraphs by connecting the materials directly onto the texture nodes. This violates some usd shade connection rules - but these are very rarely enforced and it might work for you (disclaimer : have only tried this for unreal, only suspect the issue is the same).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As I said though, the ARKIT USD spec is a small subset of what is supported in USD and so many other things may not work.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="general"&gt;import maxUsd
from pxr import Usd
from pxr import UsdShade
from pymxs import runtime as mxs

import os, sys, glob

class matFixChaser(maxUsd.ExportChaser):

    def __init__(self, factoryContext, *args, **kwargs):
        super(matFixChaser, self).__init__(factoryContext, *args, **kwargs)
        self.stage = factoryContext.GetStage()

    def isId(self, id , shader):
        info_id_attr = shader.GetIdAttr()
        if info_id_attr:
            id_value = info_id_attr.Get()
            return id_value == id
        return False

    def PostExport(self):
        try:
            print("Running Unreal UsdPreviewSurface fix chaser...")
            
            all_shaders = [x for x in self.stage.Traverse() if UsdShade.Shader(x)]
            for prim in all_shaders:
                
                shader = UsdShade.Shader(prim)                
                if self.isId('UsdPreviewSurface', shader):
                    
                     # Iterate over the shader's inputs
                    for input in shader.GetInputs():
                        # Check if the input is connected
                        if input.HasConnectedSource():
                            # Get the connected path
                            source = input.GetConnectedSource()
                            source_prim = source[0].GetPrim()
                            
                            # The node graph connection...
                            connection_path = source_prim.GetPath()
                            # print(connection_path)
                            
                            # Instead connect to the USD texture 2d that lives inside the node graph.
                            new_connection = connection_path.AppendChild(source_prim.GetName())
                            # print(new_connection)
                            
                            texture = UsdShade.Shader(self.stage.GetPrimAtPath(new_connection))
                            input.ConnectToSource(texture.ConnectableAPI(), 'rgb')
                            
                            
                    continue
                if self.isId('UsdPrimvarReader_float2', shader):                    
                    varname_input = shader.GetInput("varname")
                    varname_value_attributes = varname_input.GetValueProducingAttributes()
                    primvar_name = varname_value_attributes[0].Get()
                    # Punch in value directly, not from nodegraph...
                    varname_input.Set(primvar_name)
                                        
                            
        except Exception as e:
            print('Chaser ERROR : %s' % str(e))
            print(traceback.format_exc())
        
        return True

        
maxUsd.ExportChaser.Register(matFixChaser, "unrealMatFixer", "Unreal UsdPreviewSurface fix chaser", "Connects straight to textures, bypassing nodegraphs.")


def unrealMatFixContext():
    extraArgs = {}    
    extraArgs['chaser']  = ['unrealMatFixer']
    extraArgs['chaserNames']  = ['unrealMatFixer']
    return extraArgs

registeredContexts = maxUsd.JobContextRegistry.ListJobContexts()
if 'unrealMatFixContext' not in registeredContexts:
    maxUsd.JobContextRegistry.RegisterExportJobContext("unrealMatFixContext", "Fix USD Preview Surface for Unreal", "Fixes USD preview surface materials for usage in Unreal, avoiding NodeGraphs.", unrealMatFixContext)

print("Registered unreal material fixer")&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 09 Oct 2024 20:17:15 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13074938#M1871</guid>
      <dc:creator>julien.deboise</dc:creator>
      <dc:date>2024-10-09T20:17:15Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075123#M1872</link>
      <description>&lt;P&gt;Thank you! I will try the code this week and let you know how it goes.&lt;/P&gt;</description>
      <pubDate>Wed, 09 Oct 2024 21:59:20 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075123#M1872</guid>
      <dc:creator>ian3GB9G</dc:creator>
      <dc:date>2024-10-09T21:59:20Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075337#M1873</link>
      <description>&lt;P&gt;I'm not the best with scripting. I copy/pasted and saved as a &lt;STRONG&gt;.ms&lt;/STRONG&gt; in the max script startup folder. When I manually ran it I got an error. How should I proceed?&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 10 Oct 2024 00:55:13 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075337#M1873</guid>
      <dc:creator>ian3GB9G</dc:creator>
      <dc:date>2024-10-10T00:55:13Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075385#M1874</link>
      <description>&lt;P&gt;It is a python script, not maxscript - you need to save it as a .py file instead so that 3dsmax knows to run it as Python before running it manually. I dont think startup scripts can be python - but you can do this :&amp;nbsp;&lt;A href="https://help.autodesk.com/view/MAXDEV/2023/ENU/?guid=MAXDEV_Python_using_pymxs_pymxs_differences_pymxs_startup_scripts_html" target="_blank"&gt;https://help.autodesk.com/view/MAXDEV/2023/ENU/?guid=MAXDEV_Python_using_pymxs_pymxs_differences_pymxs_startup_scripts_html&lt;/A&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 10 Oct 2024 01:43:43 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075385#M1874</guid>
      <dc:creator>julien.deboise</dc:creator>
      <dc:date>2024-10-10T01:43:43Z</dc:date>
    </item>
    <item>
      <title>Re: USDZ not including textures using typical export workflow</title>
      <link>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075473#M1875</link>
      <description>&lt;P&gt;Thank you so much! It worked perfectly.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 10 Oct 2024 03:06:34 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/3ds-max-forum/usdz-not-including-textures-using-typical-export-workflow/m-p/13075473#M1875</guid>
      <dc:creator>ian3GB9G</dc:creator>
      <dc:date>2024-10-10T03:06:34Z</dc:date>
    </item>
  </channel>
</rss>

