MaterialXMaterials 1.39.5
Utilities for retrieving materials from remote servers
Loading...
Searching...
No Matches
materialxMaterials.physicallyBasedMaterialXCmd Namespace Reference

Command to convert Physically Based Materials to MaterialX Command Line Utility. More...

Functions

 physicallBasedMaterialXCmd ()
 Command to parse PhysicallyBased materials and create MaterialX materials.

Detailed Description

Command to convert Physically Based Materials to MaterialX Command Line Utility.

This script converts Physically Based Materials to MaterialX using the MaterialX Python API.

The script can be run from the command line with the following options:

–shadingModel: Shading models to use for conversion. If not specified then all will be used.

Options: standard_surface, gltf_pbr, open_pbr_surface

–outputDir: Output directory for MaterialX files

–writeJSON: Write materials JSON file. Default is True

–separateFiles: Convert individual MaterialX files per material. Default is false

Example usage:

Function Documentation

◆ physicallBasedMaterialXCmd()

materialxMaterials.physicallyBasedMaterialXCmd.physicallBasedMaterialXCmd ( )

Command to parse PhysicallyBased materials and create MaterialX materials.

Definition at line 26 of file physicallyBasedMaterialXCmd.py.

26def physicallBasedMaterialXCmd():
27 '''
28 Command to parse PhysicallyBased materials and create MaterialX materials
29 '''
30 logger = logging.getLogger('PB_CMD')
31 logging.basicConfig(level=logging.INFO)
32
33 # TODO: Add arguments for shading model, and output directory using argparse
34 parser = argparse.ArgumentParser(description='Convert Physically Based Materials to MaterialX')
35 parser.add_argument('-m', '--shadingModel', type=str, default='', help='Shading models to use for conversion. '
36 ' If not specified then all will be used. '
37 ' Options: standard_surface, gltf_pbr, open_pbr_surface')
38 parser.add_argument('-o', '--outputDir', type=str, default='',
39 help='Output directory for MaterialX files. Default location is PhysicallyBasedMaterialX')
40 parser.add_argument('-j', '--writeJSON', type=bool, default=True,
41 help='Write materials JSON file. Default is True')
42 parser.add_argument('-s', '--separateFiles', type=bool, default=False,
43 help='Convert individual MaterialX files per material. Default is false')
44 parser.add_argument('-l', '--loadFromFile', type=str, default='', help='Load materials a specified file')
45 parser.add_argument('-wr', '--writeRemapping', type=bool, default=False, help='Write remapping from PhysicallyBased to MaterialX. Default is False')
46 parser.add_argument('-rr', '--readRemapping', type=str, default='', help='Read remapping from PhysicallyBased to MaterialX. Default is empty')
47 parser.add_argument('-nd', '--createNodeDef', type=bool, default=False, help='Create NodeDef for Physically Based Material inputs. Default is False')
48 opts = parser.parse_args()
49
50 outputDir = 'PhysicallyBasedMaterialX'
51 if opts.outputDir:
52 if not os.path.exists(opts.outputDir):
53 logger.info(f'Error: Output directory does not exist: {opts.outputDir}')
54 # Create the output directory
55 try:
56 os.makedirs(opts.outputDir)
57 logger.info(f'> Created output directory: {opts.outputDir}')
58 outputDir = opts.outputDir
59 except Exception as e:
60 logger.info(f'> Error: Could not create output directory: {opts.outputDir}')
61 sys.exit(1)
62 else:
63 outputDir = opts.outputDir
64
65 shadingModels = []
66 if opts.shadingModel:
67 shadingModels = opts.shadingModel.split(',')
68 shadingModePrefixMap = { 'standard_surface': 'SS', 'gltf_pbr': 'GLTF', 'open_pbr_surface': 'OPBR' }
69 shadingModelPrefixes = []
70 if len(shadingModels) == 0:
71 shadingModels = ['standard_surface', 'gltf_pbr', 'open_pbr_surface']
72 shadingModelPrefixes = ['SS', 'GLTF', 'OPBR']
73 else:
74 for shadingModel in shadingModels:
75 shadingModelPrefixes.append(shadingModePrefixMap[shadingModel])
76
77 writeJSON = opts.writeJSON
78 separateFiles = opts.separateFiles
79
80 material_file = opts.loadFromFile
81 if material_file:
82 if not os.path.exists(opts.loadFromFile):
83 logger.info(f'> Error: File does not exist: {material_file}')
84 sys.exit(1)
85 logger.info(f'> Load materials from file: {material_file}')
86
87 # Create loader and get PhysicallyBasedMaterials
88 # Uses default remapping.
89 loader = pbmx.PhysicallyBasedMaterialLoader(mx, None, material_file)
90
91 readRemapping = opts.readRemapping
92 if readRemapping:
93 if not os.path.exists(readRemapping):
94 logger.info(f'> Error: Remapping file does not exist: {readRemapping}')
95 logger.info(f'> Read remapping file: {readRemapping}')
96 loader.readRemappingFile(readRemapping)
97 else:
98 writeRemapping = opts.writeRemapping
99 if writeRemapping:
100 outputFile = os.path.join(outputDir, 'PhysicallyBasedToMtlxMappings.json')
101 logger.info(f'> Write remapping file: {outputFile}')
102 loader.writeRemappingFile(outputFile)
103
104 jsonMat = loader.getJSON()
105 if jsonMat:
106
107 # Create folder for MaterialX call PhysicallyBasedMaterialX
108 os.makedirs(outputDir, exist_ok=True)
109
110 create_nodedef = opts.createNodeDef
111 if create_nodedef:
112
113 # Write PhysicallyBased BSDF definition
114 #
115 logger.info('> Write definition for PhysicallyBased materials')
116 definitions_doc = loader.get_physlib()
117 if definitions_doc:
118 nodedef_file_name = os.path.join(outputDir, 'physbased_pbr.mtlx')
119 mx.writeToXmlFile(definitions_doc, nodedef_file_name)
120 logger.info(f'> Write definition file: {nodedef_file_name}')
121
122 # Get PhysicallyBased materials using the definition
123 #
124 doc_mat = loader.get_physlib_materials()
125 if doc_mat:
126 status, error = doc_mat.validate()
127 if not status:
128 logger.error('> Error validating definition materials document:')
129 logger.error(error)
130 else:
131 logger.info('> Definition materials document passed validation.')
132
133 nodedef_mat_file_name = os.path.join(outputDir, 'physbased_pbr_materials.mtlx')
134 mx.writeToXmlFile(doc_mat, mx.FilePath(nodedef_mat_file_name))
135 logger.info(f'> Write materials file: {nodedef_mat_file_name}')
136
137 # Write out translator definitions
138 #
139 translators_doc = loader.get_translators()
140 translators = translators_doc.getNodeDefs()
141 print(f'Found translator definitions: {len(translators)}')
142
143 if translators_doc and translators:
144 output_file_name = 'physbased_pbr_translators.mtlx'
145 output_path = os.path.join(outputDir, output_file_name)
146 logger.info('> Write translator file:' + output_path)
147 mx.writeToXmlFile(translators_doc, mx.FilePath(output_path))
148
149 # Get doc with all required definitions: stdlib, PhysicallyBased definition, and translator definitions
150 stdlib = loader.get_definitions()
151
152 # Export single file with all translated materials
153 if not separateFiles:
154 translated_doc = loader.get_physlib_materials()
155
156 # Copy over materials + reference libraries
157 #translated_doc.copyContentFrom(doc_mat)
158 #translated_doc.setDataLibrary(doc_mat.getDataLibrary())
159
160 for shadingModel, prefix in zip(shadingModels, shadingModelPrefixes):
161
162 for node in translated_doc.getNodes():
163 if node.getCategory() == loader.get_physlib_category():
164 trans_result = loader.translate_node(translated_doc, loader.get_physlib_category(), shadingModel, node)
165
166 logger.info(f'> Generate MaterialX using nodedefs for shading model: {shadingModel}')
167 fileName = os.path.join(outputDir, f'PhysicallyBasedMaterialX_translated_{prefix}.mtlx')
168 loader.writeMaterialXToFile(fileName, translated_doc)
169 logger.info(f'> Write: {fileName}')
170
171 # Export separate files per translated material
172 else:
173 matDir = os.path.join(outputDir, 'Sep')
174 os.makedirs(matDir, exist_ok=True)
175 for shadingModel, prefix in zip(shadingModels, shadingModelPrefixes):
176 converted = []
177 for mat in loader.getJSONMaterialNames():
178 materialFilter = [mat]
179
180 # Create doc with single material
181 matdoc = loader.create_definition_materials(None, materialFilter)
182 if matdoc is not None:
183
184 # Translate the material
185 mat_name = mx.createValidName(mat)
186 node = matdoc.getNode(mat_name)
187 if node:
188 trans_result = loader.translate_node(matdoc, loader.get_physlib_category(), shadingModel, node)
189 if not trans_result:
190 logger.warning(f'Failed to translate node: {mat_name} for shading model: {shadingModel}')
191 else:
192 converted.append(trans_result['targetNode'].getName())
193 valid, errors = loader.validateMaterialXDocument(matdoc)
194 if valid:
195 #logger.info(f'> Generate material {mat_name} for shading model: {shadingModel}')
196 fileName = os.path.join(matDir, f'PB_{prefix}_{mat}.mtlx')
197 loader.writeMaterialXToFile(fileName, matdoc)
198
199 logger.info(f'> Converted {len(converted)} materials for shading model: {shadingModel}')
200
201 if writeJSON:
202 logger.info(f'> Write PB material file: {outputDir}/PhysicallyBasedMaterial.json')
203 loader.writeJSONToFile(os.path.join(outputDir, 'PhysicallyBasedMaterial.json'))
204
205 if create_nodedef:
206 return
207
208 # Direct translation from JSON to MaterialX path. Skip if using PhysicallyBased nodedefs
209 if not separateFiles:
210 for shadingModel, prefix in zip(shadingModels, shadingModelPrefixes):
211 logger.info(f'> Generate MaterialX for shading model: {shadingModel}')
212 matdoc = loader.convertToMaterialX([], shadingModel, {}, prefix)
213 valid, errors = loader.validateMaterialXDocument(matdoc)
214 if valid:
215 fileName = os.path.join(outputDir, f'PhysicallyBasedMaterialX_{prefix}.mtlx')
216 loader.writeMaterialXToFile(fileName)
217 logger.info(f'> Write: {fileName}')
218
219 else:
220 for shadingModel, prefix in zip(shadingModels, shadingModelPrefixes):
221 logger.info(f'> Generate MaterialX for shading model: {shadingModel}')
222 for mat in loader.getJSONMaterialNames():
223 materialFilter = [mat]
224 matdoc = loader.convertToMaterialX(materialFilter, shadingModel, {}, prefix)
225 if matdoc is not None:
226 valid, errors = loader.validateMaterialXDocument(matdoc)
227 if valid:
228 fileName = os.path.join(outputDir, f'PB_{prefix}_{mat}.mtlx')
229 loader.writeMaterialXToFile(fileName)
230 logger.info(f'> Write: {fileName}')
231
232 else:
233 logger.info('Could not retrieve PhysicallyBased Materials')
234