MaterialXUSD 0.0.1
Utilities for using MaterialX with USD
Loading...
Searching...
No Matches
materialxusd.materialxusd.MaterialxUSDConverter Class Reference

Class that converts a MaterialX file to a USD file with an appropriate scene. More...

Public Member Functions

 __init__ (self)
 Constructor for the MaterialxUSDConverter class.
 
 validate_stage (self, str file, bool verboseOutput=False)
 This function validates a USD file using the ComplianceChecker.
 
 find_first_valid_prim (self, stage)
 This function finds the first valid prim in root layer of a stage.
 
 set_required_validation_attributes (self, stage)
 This function sets the required validation attributes for the stage.
 
 find_materials (self, stage, bool find_first=True)
 This function finds the first material in the stage.
 
 add_skydome_light (self, Usd.Stage stage, str environment_path, str root_path="/TestScene/Lights", str light_name="EnvironmentLight", xform_scale=Gf.Vec3f(1.3, 1.3, 1.3), xform_rotate=Gf.Vec3f(0, 0, 0))
 This function adds a skydome light to the stage.
 
 add_geometry_reference (self, Usd.Stage stage, str geometry_path, str root_path="/TestScene/Geometry")
 This function adds a geometry reference to the stage.
 
 find_first_camera (self, Usd.Stage stage)
 This function finds the first camera in the stage.
 
 add_camera (self, Usd.Stage stage, str camera_path, str root_path="/TestScene/Camera", str geometry_path="/TestScene/Geometry")
 This function adds a camera to the stage.
 
 mtlx_to_usd (self, str input_usd_path, str shaderball_path, str environment_path, str material_file_path, str camera_path, use_custom=False)
 This function reads the input usd file and adds the shaderball geometry and environment light to the scene.
 
 get_flattend_layer (self, stage)
 This function flattens the stage and returns the flattened layer.
 
 save_flattened_layer (self, flattened_layer, str output_path)
 This function saves the flattened stage to a new USD file.
 
 create_usdz_package (self, str usdz_file_path, flattened_layer)
 This function creates a new USDZ package from a flattened layer.
 

Public Attributes

 logger = logging.getLogger('MX2USD')
 

Detailed Description

Class that converts a MaterialX file to a USD file with an appropriate scene.

Definition at line 10 of file materialxusd.py.

Constructor & Destructor Documentation

◆ __init__()

materialxusd.materialxusd.MaterialxUSDConverter.__init__ ( self)

Constructor for the MaterialxUSDConverter class.

Definition at line 14 of file materialxusd.py.

14 def __init__(self):
15 '''
16 @brief Constructor for the MaterialxUSDConverter class.
17 '''
18 logging.basicConfig(level=logging.INFO)
19 self.logger = logging.getLogger('MX2USD')
20
21

Member Function Documentation

◆ add_camera()

materialxusd.materialxusd.MaterialxUSDConverter.add_camera ( self,
Usd.Stage stage,
str camera_path,
str root_path = "/TestScene/Camera",
str geometry_path = "/TestScene/Geometry" )

This function adds a camera to the stage.

Parameters
stageThe stage to add the camera.
camera_pathThe path to the camera file.
root_pathThe root path to add the camera.
geometry_pathThe path to the geometry file.

Definition at line 169 of file materialxusd.py.

169 def add_camera(self, stage : Usd.Stage, camera_path : str, root_path : str="/TestScene/Camera", geometry_path : str="/TestScene/Geometry"):
170 '''
171 @brief This function adds a camera to the stage.
172 @param stage: The stage to add the camera.
173 @param camera_path: The path to the camera file.
174 @param root_path: The root path to add the camera.
175 @param geometry_path: The path to the geometry file.
176 '''
177 if camera_path:
178 camera = stage.DefinePrim(root_path, "Xform")
179 camera.GetReferences().AddReference(camera_path)
180 return camera
181
182 # Define the geometry path (e.g., a cube or any other geometry)
183 geometry_path = Sdf.Path(geometry_path)
184
185 # Get the UsdPrim for the geometry
186 geometry_prim = stage.GetPrimAtPath(geometry_path)
187
188 camera_path = Sdf.Path(root_path)
189 camera = UsdGeom.Camera.Define(stage, camera_path)
190
191 # Compute the world space bounding box of the geometry
192 bbox_cache = UsdGeom.BBoxCache(Usd.TimeCode.Default(), [UsdGeom.Tokens.default_])
193 bbox = bbox_cache.ComputeWorldBound(geometry_prim)
194 bbox_range = bbox.ComputeAlignedRange()
195
196 # Get the center and size of the bounding box
197 bbox_center = bbox_range.GetMidpoint() # This is a Gf.Vec3d
198 bbox_size = bbox_range.GetSize() # This is a Gf.Vec3d
199
200 # Position the camera to frame the bounding box
201 # Move the camera back along the Z-axis to fit the bounding box
202 distance = max(bbox_size) * 1.5 # Adjust the multiplier as needed
203
204 # Convert bbox_center to Gf.Vec3f for compatibility with Gf.Vec3f(0, 0, distance)
205 camera_position = Gf.Vec3f(bbox_center) + Gf.Vec3f(0, 0, distance)
206 camera.AddTranslateOp().Set(camera_position)
207
208 # Orient the camera to look at the center of the bounding box
209 camera.AddRotateYOp().Set(0) # Rotate to look along the -Z axis
210 look_at = UsdGeom.XformCommonAPI(camera)
211 look_at.SetRotate((0, 0, 0)) # Ensure the camera is aligned
212
213 # Adjust the camera's field of view to fit the bounding box
214 focal_length = 35.0 # Default focal length
215 camera.GetFocalLengthAttr().Set(focal_length)
216
217 # Set the horizontal and vertical aperture to ensure proper framing
218 horizontal_aperture = bbox_size[0] / bbox_size[1] * 20.0 # Adjust based on aspect ratio
219 vertical_aperture = horizontal_aperture
220 camera.GetHorizontalApertureAttr().Set(horizontal_aperture)
221 camera.GetVerticalApertureAttr().Set(vertical_aperture)
222
223 # Set the clipping range to include the bounding box
224 near_clip = distance - max(bbox_size) * 0.5
225 far_clip = distance + max(bbox_size) * 0.5
226 camera.GetClippingRangeAttr().Set(Gf.Vec2f(near_clip, far_clip))
227
228 #camera.SetActive(True)
229
230 # Save the USD stage
231 return camera
232

◆ add_geometry_reference()

materialxusd.materialxusd.MaterialxUSDConverter.add_geometry_reference ( self,
Usd.Stage stage,
str geometry_path,
str root_path = "/TestScene/Geometry" )

This function adds a geometry reference to the stage.

Parameters
stageThe stage to add the geometry reference.
geometry_pathThe path to the geometry file.
root_pathThe root path to add the geometry reference.

Definition at line 145 of file materialxusd.py.

145 def add_geometry_reference(self, stage: Usd.Stage, geometry_path : str, root_path : str="/TestScene/Geometry"):
146 '''
147 @brief This function adds a geometry reference to the stage.
148 @param stage: The stage to add the geometry reference.
149 @param geometry_path: The path to the geometry file.
150 @param root_path: The root path to add the geometry reference.
151 '''
152 geom_prim = stage.DefinePrim(root_path, "Xform")
153 geom_prim.GetReferences().AddReference(geometry_path)
154 return geom_prim
155

◆ add_skydome_light()

materialxusd.materialxusd.MaterialxUSDConverter.add_skydome_light ( self,
Usd.Stage stage,
str environment_path,
str root_path = "/TestScene/Lights",
str light_name = "EnvironmentLight",
xform_scale = Gf.Vec3f(1.3, 1.3, 1.3),
xform_rotate = Gf.Vec3f(0, 0, 0) )

This function adds a skydome light to the stage.

Parameters
stageThe stage to add the skydome light.
environment_pathThe path to the environment light file.
root_pathThe root path to add the skydome light.
light_nameThe name of the skydome light.
xform_scaleThe scale of the skydome light.
xform_rotateThe rotation of the skydome light.
Returns
: The skydome light added to the stage.

Definition at line 102 of file materialxusd.py.

102 def add_skydome_light(self, stage: Usd.Stage, environment_path:str, root_path:str = "/TestScene/Lights", light_name:str = "EnvironmentLight", xform_scale=Gf.Vec3f(1.3, 1.3, 1.3), xform_rotate=Gf.Vec3f(0, 0, 0)):
103 '''
104 @brief This function adds a skydome light to the stage.
105 @param stage: The stage to add the skydome light.
106 @param environment_path: The path to the environment light file.
107 @param root_path: The root path to add the skydome light.
108 @param light_name: The name of the skydome light.
109 @param xform_scale: The scale of the skydome light.
110 @param xform_rotate: The rotation of the skydome light.
111 @return: The skydome light added to the stage.
112 '''
113 skydome_prim = stage.DefinePrim(root_path, "Xform")
114 # Make the skydome prim Xformable
115 xformable = UsdGeom.Xformable(skydome_prim)
116
117 # Scale drawing of skydome
118 scale_op = xformable.GetScaleOp()
119 if not scale_op:
120 scale_op = xformable.AddScaleOp(UsdGeom.XformOp.PrecisionFloat)
121 scale_value = xform_scale
122 scale_op.Set(scale_value)
123
124 dome_light = UsdLux.DomeLight.Define(stage, f"{root_path}/{light_name}")
125
126 # Set the attributes for the DomeLight
127 dome_light.CreateIntensityAttr().Set(1.0)
128 dome_light.CreateTextureFileAttr().Set(environment_path)
129
130 # Set guideRadius
131 dome_light.CreateGuideRadiusAttr().Set(1.0)
132
133 # Rotate the light as needed.
134 xformable = UsdGeom.Xformable(dome_light)
135 xform_op = xformable.GetXformOp(UsdGeom.XformOp.TypeRotateXYZ)
136 if not xform_op:
137 xform_op = xformable.AddXformOp(UsdGeom.XformOp.TypeRotateXYZ, UsdGeom.XformOp.PrecisionFloat)
138 xform_op.Set(xform_rotate)
139
140 # Set the xformOpOrder
141 xformable.SetXformOpOrder([xform_op])
142
143 return dome_light
144

◆ create_usdz_package()

materialxusd.materialxusd.MaterialxUSDConverter.create_usdz_package ( self,
str usdz_file_path,
flattened_layer )

This function creates a new USDZ package from a flattened layer.

Parameters
usdz_file_pathThe path to the USDZ package to create.
flattened_layerThe flattened layer to save to the USDZ package.
Returns
: True if the USDZ package was successfully created, False otherwise.

Definition at line 335 of file materialxusd.py.

335 def create_usdz_package(self, usdz_file_path:str, flattened_layer):
336 '''
337 @brief This function creates a new USDZ package from a flattened layer.
338 @param usdz_file_path: The path to the USDZ package to create.
339 @param flattened_layer: The flattened layer to save to the USDZ package.
340 @return: True if the USDZ package was successfully created, False otherwise.
341 '''
342 success = False
343 error = ""
344 try:
345 success = UsdUtils.CreateNewUsdzPackage(flattened_layer.identifier, usdz_file_path)
346 if not success:
347 error = ("Failed to create USDZ package.")
348 except Exception as e:
349 error = (f"An exception occurred while creating the USDZ file: {e}")
350
351 return success, error
352

◆ find_first_camera()

materialxusd.materialxusd.MaterialxUSDConverter.find_first_camera ( self,
Usd.Stage stage )

This function finds the first camera in the stage.

Parameters
stageThe stage to search for the first camera.
Returns
: The first camera found in the stage. If no camera is found, None is returned.

Definition at line 156 of file materialxusd.py.

156 def find_first_camera(self, stage : Usd.Stage):
157 '''
158 @brief This function finds the first camera in the stage.
159 @param stage: The stage to search for the first camera.
160 @return: The first camera found in the stage. If no camera is found, None is returned.
161 '''
162 # Traverse the stage's prims
163 for prim in stage.Traverse():
164 # Check if the prim is a UsdGeomCamera
165 if prim.IsA(UsdGeom.Camera):
166 return prim
167 return None
168

◆ find_first_valid_prim()

materialxusd.materialxusd.MaterialxUSDConverter.find_first_valid_prim ( self,
stage )

This function finds the first valid prim in root layer of a stage.

Parameters
stageThe stage to search for the first valid prim.
Returns
: The first valid prim found in the stage. If no valid prim is found, None is returned.

Definition at line 45 of file materialxusd.py.

45 def find_first_valid_prim(self, stage):
46 '''
47 @brief This function finds the first valid prim in root layer of a stage.
48 @param stage: The stage to search for the first valid prim.
49 @return: The first valid prim found in the stage. If no valid prim is found, None is returned.
50 '''
51 # Get the root layer of the stage
52 root_layer = stage.GetRootLayer()
53
54 # Find first valid prim
55 first_prim = None
56 for prim in stage.Traverse():
57 if prim.IsValid():
58 first_prim = prim
59 break
60
61 return first_prim
62

◆ find_materials()

materialxusd.materialxusd.MaterialxUSDConverter.find_materials ( self,
stage,
bool find_first = True )

This function finds the first material in the stage.

Assumes MaterialX materials are stored under the "/MaterialX/Materials" scope.

Parameters
stageThe stage to search for the first material.
find_firstIf True, only the first material found is returned. Default is True.
Returns
: The first material found in the stage. If no material is found, None is returned.

Definition at line 73 of file materialxusd.py.

73 def find_materials(self, stage, find_first:bool=True):
74 '''
75 @brief This function finds the first material in the stage. Assumes MaterialX
76 materials are stored under the "/MaterialX/Materials" scope.
77 @param stage: The stage to search for the first material.
78 @param find_first: If True, only the first material found is returned. Default is True.
79 @return: The first material found in the stage. If no material is found, None is returned.
80 '''
81 found_materials = []
82
83 # Find the first material under the "MaterialX/Materials" scope
84 materialx_prim = stage.GetPrimAtPath("/MaterialX")
85 if not materialx_prim:
86 self.logger.info("> Warning: Could not find /MaterialX scope in the USDA file.")
87 return found_materials
88
89 materials_prim = materialx_prim.GetPrimAtPath("Materials")
90 if not materials_prim:
91 self.logger.info("> Warning: Could not find /MaterialX/Materials scope in the USDA file.")
92 return found_materials
93
94 for child_prim in materials_prim.GetAllChildren():
95 if child_prim.GetTypeName() == "Material":
96 found_materials.append(child_prim)
97 if find_first:
98 break
99
100 return found_materials
101

◆ get_flattend_layer()

materialxusd.materialxusd.MaterialxUSDConverter.get_flattend_layer ( self,
stage )

This function flattens the stage and returns the flattened layer.

Parameters
stageThe stage to flatten.
Returns
: The flattened layer.

Definition at line 316 of file materialxusd.py.

316 def get_flattend_layer(self, stage):
317 '''
318 @brief This function flattens the stage and returns the flattened layer.
319 @param stage: The stage to flatten.
320 @return: The flattened layer.
321 '''
322 return stage.Flatten()
323

◆ mtlx_to_usd()

materialxusd.materialxusd.MaterialxUSDConverter.mtlx_to_usd ( self,
str input_usd_path,
str shaderball_path,
str environment_path,
str material_file_path,
str camera_path,
use_custom = False )

This function reads the input usd file and adds the shaderball geometry and environment light to the scene.

It also binds the first material to the shaderball geometry. The final stage is returned.

Parameters
input_usd_pathPath to the input usd file
shaderball_pathPath to the shaderball geometry file
environment_pathPath to the environment light file
material_file_pathPath to the material file. If specified will save the material file.
camera_pathPath to the camera file
Returns
: The final stage with all the elements added

Definition at line 233 of file materialxusd.py.

234 use_custom=False):
235 '''
236 @brief This function reads the input usd file and adds the shaderball geometry and environment light
237 to the scene. It also binds the first material to the shaderball geometry. The final stage is returned.
238 @param input_usd_path: Path to the input usd file
239 @param shaderball_path: Path to the shaderball geometry file
240 @param environment_path: Path to the environment light file
241 @param material_file_path: Path to the material file. If specified will save the material file.
242 @param camera_path: Path to the camera file
243 @return: The final stage with all the elements added
244 '''
245 # Open the input USDA file
246 stage = None
247
248 if use_custom:
249 mtlx_to_usd = mxcust.MtlxToUsd(self.logger)
250 stage = mtlx_to_usd.emit(input_usd_path, False)
251 else:
252 try:
253 stage = Usd.Stage.Open(input_usd_path)
254 except Exception as e:
255 self.logger.info(f"> Error: Could not open file at {input_usd_path}. Error: {e}")
256 return stage, None, None, None, None
257
258 if not stage:
259 self.logger.info(f"> Error: Could not open file at {input_usd_path}")
260 return stage, None, None, None, None
261
262 # Set the required validation attributes
263 self.set_required_validation_attributes(stage)
264
265 if material_file_path:
266 # Save the material file
267 self.logger.info(f"> Saving MaterialX content to: {material_file_path}")
268 stage.GetRootLayer().documentation = f"MaterialX content from {input_usd_path}"
269 stage.GetRootLayer().Export(material_file_path)
270
271 found_materials = self.find_materials(stage, False)
272 #if not found_materials:
273 # self.logger.info("Warning: No materials found under /MaterialX/Materials.")
274 #return stage, found_materials, None, None, None
275 first_material = found_materials[0] if found_materials else None
276
277 # TODO: Make this a user option...
278 SCENE_ROOT = "/TestScene"
279 GEOM_ROOT = "/TestScene/Geometry"
280 LIGHTS_ROOT = "/TestScene/Lights"
281 SKYDOME_LIGHT_NAME = "EnvironmentLight"
282
283 # Define the scene prim
284 test_scene_prim = stage.DefinePrim(SCENE_ROOT, "Xform")
285 # - Specify a default prim for validation
286 stage.SetDefaultPrim(stage.GetPrimAtPath(SCENE_ROOT))
287
288 # - Add geometry reference
289 test_geom_prim = None
290 if shaderball_path:
291 test_geom_prim = self.add_geometry_reference(stage, shaderball_path, GEOM_ROOT)
292 if test_geom_prim and first_material:
293 material_binding_api = UsdShade.MaterialBindingAPI.Apply(test_geom_prim)
294 material_binding_api.Bind(UsdShade.Material(first_material))
295 self.logger.info(f"> Geometry reference '{shaderball_path} added under: {test_scene_prim.GetPath()}.")
296
297 # Add lighting with reference to light environment file
298 # -----------------------------------------
299 dome_light = None
300 if environment_path:
301 dome_light = self.add_skydome_light(stage, environment_path, LIGHTS_ROOT, SKYDOME_LIGHT_NAME)
302 if dome_light:
303 self.logger.info(f"> Light '{environment_path}' added at path: {dome_light.GetPath()}.")
304
305 # Add camera reference
306 # -----------------------------------------
307 camera_prim = self.add_camera(stage, camera_path)
308 if camera_prim:
309 if camera_path:
310 self.logger.info(f"> Camera '{camera_path}' added at path: {camera_prim.GetPath()}.")
311 else:
312 self.logger.info(f"> Camera added at path: {camera_prim.GetPath()}.")
313
314 return stage, found_materials, test_geom_prim, dome_light, camera_prim
315

◆ save_flattened_layer()

materialxusd.materialxusd.MaterialxUSDConverter.save_flattened_layer ( self,
flattened_layer,
str output_path )

This function saves the flattened stage to a new USD file.

Parameters
flattened_layerThe flattened layer to save.
output_pathThe path to save the flattened stage.

Definition at line 324 of file materialxusd.py.

324 def save_flattened_layer(self, flattened_layer, output_path:str):
325 '''
326 @brief This function saves the flattened stage to a new USD file.
327 @param flattened_layer: The flattened layer to save.
328 @param output_path: The path to save the flattened stage.
329 '''
330 flatten_path = output_path.replace(".usda", "_flattened.usda")
331 flattened_layer.documentation = f"Flattened USD file for {output_path}"
332 flattened_layer.Export(flatten_path)
333 return flatten_path
334

◆ set_required_validation_attributes()

materialxusd.materialxusd.MaterialxUSDConverter.set_required_validation_attributes ( self,
stage )

This function sets the required validation attributes for the stage.

For now this function sets the upAxis and metersPerUnit. to Y and 1.0 respectively.

Parameters
stageThe stage to set the required validation attributes.

Definition at line 63 of file materialxusd.py.

63 def set_required_validation_attributes(self, stage):
64 '''
65 @brief This function sets the required validation attributes for the stage.
66 For now this function sets the upAxis and metersPerUnit. to Y and 1.0 respectively.
67 @param stage: The stage to set the required validation attributes.
68 '''
69 # Set the upAxis and metersPerUnit for validation
70 UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.y)
71 UsdGeom.SetStageMetersPerUnit(stage, 1.0)
72

◆ validate_stage()

materialxusd.materialxusd.MaterialxUSDConverter.validate_stage ( self,
str file,
bool verboseOutput = False )

This function validates a USD file using the ComplianceChecker.

Parameters
fileThe path to the USD file to validate.
verboseOutputIf True, the compliance check will output verbose information. Default is False.
Returns
: A tuple containing the errors, warnings, and failed checks.

Definition at line 22 of file materialxusd.py.

22 def validate_stage(self, file:str, verboseOutput:bool=False):
23 '''
24 @brief This function validates a USD file using the ComplianceChecker.
25 @param file: The path to the USD file to validate.
26 @param verboseOutput: If True, the compliance check will output verbose information. Default is False.
27 @return: A tuple containing the errors, warnings, and failed checks.
28 '''
29 # Set up a ComplianceChecker
30 compliance_checker = UsdUtils.ComplianceChecker(
31 rootPackageOnly=False,
32 skipVariants=False,
33 verbose=verboseOutput
34 )
35
36 # Run the compliance check
37 compliance_checker.CheckCompliance(file)
38
39 # Get the results of the compliance check
40 errors = compliance_checker.GetErrors()
41 warnings = compliance_checker.GetWarnings()
42 failed_checks = compliance_checker.GetFailedChecks()
43 return errors, warnings, failed_checks
44

Member Data Documentation

◆ logger

materialxusd.materialxusd.MaterialxUSDConverter.logger = logging.getLogger('MX2USD')

Definition at line 19 of file materialxusd.py.


The documentation for this class was generated from the following file: