omni.mdl.pymdlsdk¶
This extension provides Python bindings for the MDL SDK. It consists of two modules:
pymdlsdk, which is a low-level binding automatically generated from the C++ API using SWIG.
pymdl, a hand-written high-level binding based on pymdlsdk.
Python API - pymdlsdk¶
The MDL Python Bindings are generated from the C++ sources using SWIG. For a complete API reference, the specification, and more information, please refer to NVIDIA Raytracing Docs.
Python API - pymdl¶
MDL Python Bindings - a high-level wrapper for a more efficient and user-friendly usage.
Note, this is an experimental library to simply a few of the use cases of the MDL SDK. For a complete access to the MDL SDK API, please refer to the low-level binding, pymdlsdk.py.
-
class
omni.mdl.pymdl.
Annotation
(iannotation: omni.mdl.pymdlsdk.IAnnotation)¶ Bases:
object
Wrapper around an MDL annotation.
-
property
arguments
¶ Dictionary with the annotations arguments and their values.
-
property
moduleDbName
¶ The database of the module in which the annotation is defined.
-
property
name
¶ The full name of the annotation consisting of the module name, the simple name and the parameter list.
-
property
parameterTypeNames
¶ The list of parameter type names of the signature of this annotation.
-
property
simpleName
¶ The name of the annotation within the module it is defined in without its parameter list.
-
property
-
omni.mdl.pymdl.
AnnotationBlock
(iannotation_block: omni.mdl.pymdlsdk.IAnnotation_block) → Tuple[omni.mdl.pymdl.Annotation, …]¶ Creates an immutable list of annotations from an MDL annotation block.
- Parameters
iannotation_block (pymdlsdk.IAnnotation_block) – Low level MDL annotation block proxy generated for the Python binding.
- Returns
A list of high level wrapped annotation information read from the annotation block.
- Return type
tuple(Annotation)
-
class
omni.mdl.pymdl.
Argument
(type: omni.mdl.pymdl.Type, annotations: () = ())¶ Bases:
object
Wrapper around an MDL parameter. Argument combines type information, annotations, and optionally the value of an MDL parameter.
Argument is used:
To describe the parameters of a FunctionCall. The value of the Argument is the value of the corresponding function call parameter.
To describe the parameters of a FunctionDefinition. In this case, the value of the Argument is the default value of the corresponding definition parameter if applicable (i.e. default value exists.)
To describe the Parameters of an Annotation along with its value.
To describe return types of functions and their annotations. In this case, the value is not used.
There are two kinds of Argument: ArgumentConstant and ArgumentCall. ArgumentConstant holds an actual value. ArgumentCall refers to other function calls which allows to construct expression graphs.
Argument gives access to:
- type: Type
The parameter type.
- annotations: tuple(Annotation)
The parameter annotations.
-
class
omni.mdl.pymdl.
ArgumentCall
(iexpression: omni.mdl.pymdlsdk.IExpression_call, annotations=())¶ Bases:
omni.mdl.pymdl.Argument
Wrapper around an MDL FunctionCall parameter.
ArgumentCall gives access to:
- value: str
The DB name of the referenced function call.
-
class
omni.mdl.pymdl.
ArgumentConstant
(ivalue: omni.mdl.pymdlsdk.IValue, annotations: () = ())¶ Bases:
omni.mdl.pymdl.Argument
Wrapper around an MDL parameter value.
Type gives access to:
- value: See IValueToPyValues()
Holds an actual parameter value. The MDL value is transformed using IValueToPyValues()
-
omni.mdl.pymdl.
DowncastIExpression
(iexpression: omni.mdl.pymdlsdk.IExpression) → omni.mdl.pymdlsdk.IExpression¶ Cast the input expression into the proper derived interface depending on the kind of expression.
Here is the mapping from the expression kind to the returned interface:
EK_CONSTANT –> IExpression_constant
EK_CALL –> IExpression_call
EK_PARAMETER –> IExpression_parameter
EK_DIRECT_CALL –> IExpression_direct_call
EK_TEMPORARY –> IExpression_temporary
-
omni.mdl.pymdl.
DowncastIType
(itype: omni.mdl.pymdlsdk.IType) → omni.mdl.pymdlsdk.IType¶ Cast the input type into the proper derived interface depending on the kind of type.
Here is the mapping from the type kind to the returned interface:
TK_ALIAS –> IType_alias
TK_BOOL –> IType_bool
TK_INT –> IType_int
TK_ENUM –> IType_enumeration
TK_FLOAT –> IType_float
TK_DOUBLE –> IType_double
TK_STRING –> IType_string
TK_VECTOR –> IType_vector
TK_MATRIX –> IType_matrix
TK_COLOR –> IType_color
TK_ARRAY –> IType_array
TK_STRUCT –> IType_structure
TK_TEXTURE –> IType_texture
TK_LIGHT_PROFILE –> IType_light_profile
TK_BSDF_MEASUREMENT –> IType_bsdf_measurement
TK_BSDF –> IType_bsdf
TK_HAIR_BSDF –> IType_hair_bsdf
TK_EDF –> IType_edf
TK_VDF –> IType_vdf
-
omni.mdl.pymdl.
DowncastIValue
(ivalue: omni.mdl.pymdlsdk.IValue) → omni.mdl.pymdlsdk.IValue¶ Cast the input value into the proper derived interface depending on the kind of value.
Here is the mapping from the ivalue kind to the returned interface:
VK_BOOL –> IValue_bool
VK_INT –> IValue_int
VK_ENUM –> IValue_enumeration
VK_FLOAT –> IValue_float
VK_DOUBLE –> IValue_double
VK_STRING –> IValue_string
VK_VECTOR –> IValue_vector
VK_MATRIX –> IValue_matrix
VK_COLOR –> IValue_color
VK_ARRAY –> IValue_array
VK_STRUCT –> IValue_structure
VK_INVALID_DF –> IValue_invalid_df
VK_TEXTURE –> IValue_texture
VK_LIGHT_PROFILE –> IValue_light_profile
VK_BSDF_MEASUREMENT –> IValue_bsdf_measurement
-
class
omni.mdl.pymdl.
FunctionCall
(func: omni.mdl.pymdlsdk.IFunction_call, dbName: str)¶ Bases:
object
Wrapper around MDL function call.
FunctionCall gives access to:
- functionDefinition: str
The DB name of the corresponding function definition.
- mdlFunctionDefinition: str
The MDL name of the corresponding function definition.
- parameters: Dict[str, Argument]
Dictionary of the function call parameters as Argument. Key is parameter name corresponding to the Argument.
-
class
omni.mdl.pymdl.
FunctionDefinition
(func: omni.mdl.pymdlsdk.IFunction_definition, dbName: str)¶ Bases:
object
Wrapper around MDL function definition.
FunctionDefinition gives access to:
- annotations: AnnotationBlock
The annotations of the function definition itself, or None if there are no such annotations.
- dbName: str
DB name of the function definitions.
- mdlModuleName:str
The MDL name of the module containing this function definition.
- mdlName: str
The MDL name of the function definition.
- mdlSimpleName: str
The simple MDL name of the function definition. The simple name is the last component of the MDL name, i.e., without any packages and scope qualifiers, and without the parameter type names.
- moduleDbName: str
The DB name of the module containing this function definition.
- parameters: Dict[str, Argument]
Dictionary of the function definition parameters as Argument. Key is parameter name corresponding to the Argument.
- parameterTypeNames: tuple(str)
The type name of all the parameters.
- returnValue: Argument
The return type as an Argument.
-
omni.mdl.pymdl.
IValueToPyValues
(ivalue: omni.mdl.pymdlsdk.IValue)¶ Converts low level IValues to python friendly data types.
Here is the mapping from the ivalue kind to the returned values:
VK_BOOL –> ivalue.get_value()
VK_INT –> ivalue.get_value()
VK_FLOAT –> ivalue.get_value()
VK_DOUBLE –> ivalue.get_value()
VK_STRING –> ivalue.get_value()
VK_LIGHT_PROFILE –> ivalue.get_value()
VK_BSDF_MEASUREMENT –> ivalue.get_value()
VK_ENUM –> (ivalue.get_name(), ivalue.get_value())
VK_TEXTURE –> (ivalue.get_value(), ivalue.get_gamma())
VK_COLOR –> numpy.array(color components)
VK_ARRAY –> [IValueToPyValues(array values)]
VK_STRUCT –> dict(structure field names, ArgumentConstant(structure fields))
VK_INVALID_DF –> None
For vectors (kind is VK_VECTOR), each value is converted using IValueToPyValues(). A numpy.array is returned with type depending on the vector element kind. Here is the mapping between the vector element kind and the array type.
TK_FLOAT –> numpy.float32
TK_DOUBLE –> numpy.float64
TK_INT –> numpy.int32
TK_BOOL –> bool
For matrices (kind is VK_MATRIX), each value is converted using IValueToPyValues(). A numpy.array is returned with type depending on the vector element kind. Here is the mapping between the matrix element kind and the array type.
TK_FLOAT –> numpy.float32
TK_DOUBLE –> numpy.float64
TK_INT –> numpy.int32
TK_BOOL –> bool
-
class
omni.mdl.pymdl.
Module
(transaction: omni.mdl.pymdlsdk.ITransaction, module: omni.mdl.pymdlsdk.IModule, dbName: str)¶ Bases:
object
Wrapper around an MDL module.
Module gives access to:
- dbName: str
The DB name of the module.
- filename: str
The name of the MDL source file from which the module was created.
- functionDbNames: tuple(str)
DB names of all the function definitions and the material definitions from this module.
- functions: Dict[str, FunctionDefinition]
Dictionary of FunctionDefinition. Keys is FunctionDefinition simple name.
- mdlName: str
The MDL name of the module.
- mdlSimpleName: str
The simple MDL name of the module. The simple name is the last component of the MDL name, i.e., without any packages and scope qualifiers.
-
class
omni.mdl.pymdl.
Type
(itype: omni.mdl.pymdlsdk.IType)¶ Bases:
object
Wrapper around MDL type.
Type gives access to:
- kind: Kind
The kind of type.
- symbol: str
If type is enum or struct, this is the qualified name of the enum or struct type. Otherwise this is None.
Python Example¶
To use the MDL Python Bindings in OV the omni.mdl.neuraylib is required as well. Here is a simple example to illustrate the access of the neuray instance in OV, the creation of a database transaction, and the usage of the high-level bindings.
# *****************************************************************************
# Copyright 2021 NVIDIA Corporation. All rights reserved.
# *****************************************************************************
import omni.mdl.pymdlsdk # low-level MDL python binding that matches the native SDK
import omni.mdl.pymdl # high-level wrapper
import omni.mdl.neuraylib # interface the OV material backend
import time
# check if a function is a material.
# materials don't allow overloads (for the forseeable future) and therefore don't need
# an argument list in the sub-identifier name
def isMaterial(trans: omni.mdl.pymdlsdk.ITransaction, functionDbName: str):
with trans.access_as(omni.mdl.pymdlsdk.IMaterial_definition, functionDbName) as m:
return m.is_valid_interface()
# we need the active renderer here, the rtx_scope is used by default.
# However, this is not working when Iray is active. In the future we want to get rid of that
# separation but this requires bigger changes to Iray itself.
dbScopeName = "rtx_scope" # (used as default)
# acquire neuray instance from OV
ovNeurayLib = omni.mdl.neuraylib.get_neuraylib()
ovNeurayLibHandle = ovNeurayLib.getNeurayAPI()
# feed the neuray instance into the python binding
neuray: omni.mdl.pymdlsdk.INeuray = omni.mdl.pymdlsdk.attach_ineuray(ovNeurayLibHandle)
# we need to load modules to OV using the neuraylib
# on the c++ side this is async, here it is blocking if the module is not loaded yet by the renderer
usdIdentifier = "nvidia/support_definitions.mdl"
start = time.time()
ovModule = ovNeurayLib.createMdlModule(usdIdentifier)
end = time.time()
print(f" loading '{usdIdentifier}' took {end-start} seconds.")
# create a transaction after loading so we we can see the loaded module
ovNeurayLibTransactionHandle = ovNeurayLib.createReadingTransaction(dbScopeName)
trans: omni.mdl.pymdlsdk.ITransaction = omni.mdl.pymdlsdk.attach_itransaction(ovNeurayLibTransactionHandle)
# when the module is loaded we can use the high-level python binding to inspect the module
if ovModule:
module: omni.mdl.pymdl.Module = omni.mdl.pymdl.Module._fetchFromDb(trans, ovModule.dbName)
# you can already free all low level objects here
ovNeurayLib.destroyMdlModule(ovModule)
# inspect the module
if module:
print(f" filename: {module.filename}")
print(f" dbName: {module.dbName}")
print(f" mdlName: {module.mdlName}")
print(f" mdlSimpleName: {module.mdlSimpleName}")
print(f" functions:")
for funcName in module.functions:
print(f" - name: {funcName}")
overloads = module.functions[funcName]
for func in overloads:
if isMaterial(trans, func.dbName):
print(f" * Material: {func.mdlSimpleName}")
else:
print(f" * Function: {func.mdlSimpleName} {func.parameterTypeNames}")
# Annotations
if func.annotations:
print(f" Annotations:")
anno: omni.mdl.pymdl.Annotation
for anno in func.annotations:
print(f" - Simple Name: {anno.simpleName}")
print(f" Qualified Name: {anno.name}")
arg: omni.mdl.pymdl.Argument
for arg_name, arg in anno.arguments.items():
print(f" ({arg.type.kind}) {arg_name}: {arg.value}")
# also release the transaction and neuray
if trans:
trans.abort()
trans = None
neuray = None