Command to parse PhysicallyBased materials and create MaterialX materials.
24def physicallBasedMaterialXCmd():
25 '''
26 Command to parse PhysicallyBased materials and create MaterialX materials
27 '''
28 logger = logging.getLogger('PB_CMD')
29 logging.basicConfig(level=logging.INFO)
30
31
32 parser = argparse.ArgumentParser(description='Convert Physically Based Materials to MaterialX')
33 parser.add_argument('-m', '--shadingModel', type=str, default='', help='Shading models to use for conversion. '
34 ' If not specified then all will be used. '
35 ' Options: standard_surface, gltf_pbr, open_pbr_surface')
36 parser.add_argument('-o', '--outputDir', type=str, default='',
37 help='Output directory for MaterialX files. Default location is PhysicallyBasedMaterialX')
38 parser.add_argument('-j', '--writeJSON', type=bool, default=True,
39 help='Write materials JSON file. Default is True')
40 parser.add_argument('-s', '--separateFiles', type=bool, default=False,
41 help='Convert individual MaterialX files per material. Default is false')
42 parser.add_argument('-l', '--loadFromFile', type=str, default='', help='Load materials a specified file')
43 parser.add_argument('-wr', '--writeRemapping', type=bool, default=False, help='Write remapping from PhysicallyBased to MaterialX. Default is False')
44 parser.add_argument('-rr', '--readRemapping', type=str, default='', help='Read remapping from PhysicallyBased to MaterialX. Default is empty')
45 parser.add_argument('-nd', '--createNodeDef', type=bool, default=False, help='Create NodeDef for Physically Based Material inputs. Default is False')
46 opts = parser.parse_args()
47
48 outputDir = 'PhysicallyBasedMaterialX'
49 if opts.outputDir:
50 if not os.path.exists(opts.outputDir):
51 logger.info(f'Error: Output directory does not exist: {opts.outputDir}')
52 sys.exit(1)
53 else:
54 outputDir = opts.outputDir
55
56 shadingModels = []
57 if opts.shadingModel:
58 shadingModels = opts.shadingModel.split(',')
59 shadingModePrefixMap = { 'standard_surface': 'SS', 'gltf_pbr': 'GLTF', 'open_pbr_surface': 'OPBR' }
60 shadingModelPrefixes = []
61 if len(shadingModels) == 0:
62 shadingModels = ['standard_surface', 'gltf_pbr', 'open_pbr_surface']
63 shadingModelPrefixes = ['SS', 'GLTF', 'OPBR']
64 else:
65 for shadingModel in shadingModels:
66 shadingModelPrefixes.append(shadingModePrefixMap[shadingModel])
67
68 writeJSON = opts.writeJSON
69 separateFiles = opts.separateFiles
70
71
72 jsonMat = None
73 loader = pbmx.PhysicallyBasedMaterialLoader(mx, None)
74
75 readRemapping = opts.readRemapping
76 if readRemapping:
77 if not os.path.exists(readRemapping):
78 logger.info(f'> Error: Remapping file does not exist: {readRemapping}')
79 logger.info(f'> Read remapping file: {readRemapping}')
80 loader.readRemappingFile(readRemapping)
81 else:
82 writeRemapping = opts.writeRemapping
83 if writeRemapping:
84 outputFile = os.path.join(outputDir, 'PhysicallyBasedToMtlxMappings.json')
85 logger.info(f'> Write remapping file: {outputFile}')
86 loader.writeRemappingFile(outputFile)
87
88 if opts.loadFromFile:
89 if not os.path.exists(opts.loadFromFile):
90 logger.info(f'> Error: File does not exist: {opts.loadFromFile}')
91 sys.exit(1)
92 logger.info(f'> Load materials from file: {opts.loadFromFile}')
93 jsonMat = loader.loadMaterialsFromFile(opts.loadFromFile)
94 else:
95 jsonMat = loader.getMaterialsFromURL()
96
97 if jsonMat:
98
99 create_nodedef = opts.createNodeDef
100 if create_nodedef:
101 logger.info('> Create definition for PhysicallyBased materials')
102 doc, doc_mat = loader.createNodeDef()
103
104 if doc and doc_mat:
105 status, error = doc_mat.validate()
106 if not status:
107 logger.error('> Error validating NodeDef document:')
108 logger.error(error)
109 else:
110 logger.info('> Definition documents passed validation.')
111
112 nodedef_file_name = os.path.join(outputDir, 'physbased_pbr.mtlx')
113 mx.writeToXmlFile(doc, nodedef_file_name)
114 logger.info(f'> Write definition file: {nodedef_file_name}')
115
116 nodedef_mat_file_name = os.path.join(outputDir, 'physbased_pbr_materials.mtlx')
117 mx.writeToXmlFile(doc_mat, nodedef_mat_file_name)
118 logger.info(f'> Write materials file: {nodedef_mat_file_name}')
119
120 return
121
122
123 os.makedirs(outputDir, exist_ok=True)
124
125 if writeJSON:
126 logger.info(f'> Write PB material file: {outputDir}/PhysicallyBasedMaterial.json')
127 loader.writeJSONToFile(os.path.join(outputDir, 'PhysicallyBasedMaterial.json'))
128
129 if not separateFiles:
130 for shadingModel, prefix in zip(shadingModels, shadingModelPrefixes):
131 logger.info(f'> Generate MaterialX for shading model: {shadingModel}')
132 matdoc = loader.convertToMaterialX([], shadingModel, {}, prefix)
133 valid, errors = loader.validateMaterialXDocument(matdoc)
134 if valid:
135 fileName = os.path.join(outputDir, f'PhysicallyBasedMaterialX_{prefix}.mtlx')
136 loader.writeMaterialXToFile(fileName)
137 logger.info(f'> Write: {fileName}')
138
139 else:
140 for shadingModel, prefix in zip(shadingModels, shadingModelPrefixes):
141 logger.info(f'> Generate MaterialX for shading model: {shadingModel}')
142 for mat in loader.getJSONMaterialNames():
143 materialFilter = [mat]
144 matdoc = loader.convertToMaterialX(materialFilter, shadingModel, {}, prefix)
145 if matdoc is not None:
146 valid, errors = loader.validateMaterialXDocument(matdoc)
147 if valid:
148 fileName = os.path.join(outputDir, f'PB_{prefix}_{mat}.mtlx')
149 loader.writeMaterialXToFile(fileName)
150 logger.info(f'> Write: {fileName}')
151
152 else:
153 logger.info('Could not retrieve PhysicallyBased Materials')
154