MDL-related elements comprise a set of interfaces related to the Material Definition Language (MDL). More...
Classes | |
class | mi::neuraylib::Annotation_wrapper |
A wrapper around the interfaces for MDL annotations. More... | |
class | mi::neuraylib::Argument_editor |
A wrapper around the interface for MDL material instances and function calls. More... | |
class | mi::neuraylib::Definition_wrapper |
A wrapper around the interface for MDL function definitions. More... | |
class | mi::neuraylib::ICompiled_material |
This interface represents a compiled material. More... | |
class | mi::neuraylib::IFunction_call |
This interface represents a function call. More... | |
class | mi::neuraylib::IFunction_definition |
This interface represents a function definition. More... | |
class | mi::neuraylib::IMaterial_instance |
This interface represents a material instance. More... | |
class | mi::neuraylib::IModule |
This interface represents an MDL module. More... | |
MDL-related elements comprise a set of interfaces related to the Material Definition Language (MDL).
See [MDLTI] for a technical introduction into the Material Definition Language and [MDLLS] for the language specification. See also MDL type system.
The unit of compilation in MDL is a module. Importing an MDL module creates an instance of mi::neuraylib::IModule in the DB. A module allows to retrieve the referenced (aka imported) modules, as well as the exported material and function definitions. For all exported definitions, DB elements of type mi::neuraylib::IFunction_definition are created in the DB accordingly. Both, material and function definitions can be instantiated. Those instantiations are represented by the interface mi::neuraylib::IFunction_call.
There are four different types of names for MDL elements: DB names, MDL names, simple MDL names, and serialized names.
Encoded names are a naming scheme for MDL elements. Its purpose is to avoid certain problems that exist with the old naming scheme, especially in the context of package and module names containing certain meta-characters. For example, given the function name "::f::g(int)::h::i(j::k)"
: does the signature start at the first or second left parenthesis?
The main idea is to use percent-encoding for certain characters when they do not appear as meta-character.
Decoded character | Encoded character |
---|---|
( | %28 |
) | %29 |
< | %3C |
> | %3E |
, | %2C |
: | %3A |
$ | %24 |
# | %23 |
? | %3F |
@ | %40 |
% | %25 |
To avoid redundant representations, only upper-case letters are used as hexadecimal digits of encoded characters. All characters not listed in the table above are never encoded.
Encoding these characters when they do not appear as meta-characters avoids the known ambiguities. The example from above would be either "::f::g(int%29::h::i%28j::k)"
(if the signature starts at the first left parenthesis) or "::f::g%28int%29::h::i(j::k)"
(if the signature starts at the second left parenthesis).
An important consequence from resolving such ambiguities is the fact that it is always possible to decode an encoded name, whereas (in general) it is not possible to encode a name without context. Therefore, you should use encoded names as much as possible, and use decoded names only e.g. for display purposes.
DB names are the most prominent type of names for MDL elements in the MDL SDK API. These type names are mainly used to identify MDL elements, in particular, to access them in the database.
The DB names for modules as well as for function and material definitions have an "mdl"
or "mdle"
prefix. This prefix is also used for automatically created function calls and materials instances used as parameter defaults. User-generated function calls, material instances, and compiled materials might use the prefix, but are not required to.
If the interface of an MDL element is given, then its DB name can be obtained from mi::neuraylib::ITransaction::name_of().
Decoded DB names are shown in the table below only for better understanding and comparison with subsequent tables. There is hardly any use of them, except for dealing with older file formats.
MDL entity | Decoded name | Encoded name |
---|---|---|
module with builtins | mdl::<builtins> | mdl::%3Cbuiltins%3E |
user module | mdl::foo | mdl::foo |
MDLE module (Linux) | mdle::/path/to/bar.mdle (1) | mdle::/path/to/bar.mdle (1) |
MDLE module (Windows) | mdle::/C:/path/to/bar.mdle (1) | mdle::/C%3A/path/to/bar.mdle (1) |
builtin function | mdl::operator+(float,float) | mdl::operator+(float,float) |
builtin function, affected by encoding | mdl::operator<<(int,int) | mdl::operator%3C%3C(int,int) |
builtin template-like function | mdl::operator?(bool,<0>,<0>) | mdl::operator%3F(bool,%3C0%3E,%3C0%3E) |
user function | mdl::foo::my_func(color) | mdl::foo::my_func(color) |
user function, module name affected by encoding | mdl::foo,bar::my_func(::foo,bar::my_enum) | mdl::foo%2Cbar::my_func(::foo%2Cbar::my_enum) |
user material | mdl::foo::my_mat(color) | mdl::foo::my_mat(color) |
(1) Note that the DB name for an MDLE module is not the same as the filename (modulo "mdle::"
prefix), in particular on Windows (slash before drive letter, encoded colon after drive letter, slashes vs backslashes). Even on non-Windows systems there might be differences due to filename normalization. Use mi::neuraylib::IMdl_factory::get_db_module_name() to obtain the DB name for an MDLE module from the filename.
MDL names are useful for display purposes. They are similar to the DB names, except that they lack the "mdl"
or "mdle"
prefix. Entities from the ::<builtins>
module also lack the leading scope "::"
.
The interfaces for modules as well as for function and material definitions provide methods to obtain the MDL name, see mi::neuraylib::IModule::get_mdl_name(), and mi::neuraylib::IFunction_definition::get_mdl_name(). The corresponding DB name can be obtained from an MDL name with the help of the methods mi::neuraylib::IMdl_factory::get_db_module_name() and mi::neuraylib::IMdl_factory::get_db_definition_name(). Note that there is no MDL name for function calls, material instances, or compiled materials.
For display purposes you might want to decode the MDL name using mi::neuraylib::IMdl_factory::decode_name().
MDL entity | Decoded name | Encoded name |
---|---|---|
module with builtins | ::<builtins> | ::%3Cbuiltins%3E |
user module | ::foo | ::foo |
MDLE module (Linux) | ::/path/to/bar.mdle (2) | ::/path/to/bar.mdle (2) |
MDLE module (Windows) | ::/C:/path/to/bar.mdle (2) | ::/C%3A/path/to/bar.mdle (2) |
builtin function | operator+(float,float) | operator+(float,float) |
builtin function, affected by encoding | operator<<(int,int) | operator%3C%3C(int,int) |
builtin template-like function | operator?(bool,<0>,<0>) | operator%3F(bool,%3C0%3E,%3C0%3E) |
user function | ::foo::my_func(color) | ::foo::my_func(color) |
user function, module name affected by encoding | ::foo,bar::my_func(::foo,bar::my_enum) | ::foo%2Cbar::my_func(::foo%2Cbar::my_enum) |
user material | ::foo::my_mat(color) | ::foo::my_mat(color) |
(2) Note that the MDL name for an MDLE module is not the same as the filename (modulo "::"
prefix), in particular on Windows (slash before drive letter, encoded colon after drive letter, slashes vs backslashes). Even on non-Windows systems there might be differences due to filename normalization.
Simple MDL names are a variant of the MDL names above. They are used in a few places when the context is clear. Simple MDL names for modules lack the package name prefix including the scope separator. Simple MDL names for function, material, and annotation definitions lack the module name prefix including the scope separator and the signature suffix.
Note that due to function overloading, multiple functions within a module might share the same simple name.
The interfaces for modules as well as for function and material definitions provide methods to obtain the simple MDL name, see mi::neuraylib::IModule::get_mdl_simple_name(), and mi::neuraylib::IFunction_definition::get_mdl_simple_name().
For display purposes you might want to decode the simple MDL name using mi::neuraylib::IMdl_factory::decode_name().
MDL entity | Decoded name | Encoded name |
---|---|---|
module with builtins | <builtins> | %3Cbuiltins%3E |
user module | foo | foo |
MDLE module (Linux) | /path/to/bar.mdle (3) | /path/to/bar.mdle (3) |
MDLE module (Windows) | /C:/path/to/bar.mdle (3) | /C%3A/path/to/bar.mdle (3) |
builtin function | operator+ | operator+ |
builtin function, affected by encoding | operator<< | operator%3C%3C |
builtin template-like function | operator? | operator%3F |
user function | my_func | my_func |
user function, module name affected by encoding | my_func | my_func |
user material | my_mat | my_mat |
(3) Note that the simple MDL name for an MDLE module is not the same as the filename, in particular on Windows (slash before drive letter, encoded colon after drive letter, slashes vs backslashes). Even on non-Windows systems there might be differences due to filename normalization.
Serialized names are identical to encoded DB names with the exception of Template-like function definitions. For these functions, the serialized names have a suffix in angle brackets that contains additional information about the template parameters. This extra information is useful to reconstruct the correct template instance upon deserialization. See Template-like function definitions for an example of serialized names for each template-like function.
The methods mi::neuraylib::IMdl_impexp_api::serialize_function_name(), mi::neuraylib::IMdl_impexp_api::deserialize_function_name(), and mi::neuraylib::IMdl_impexp_api::deserialize_module_name() deal with serialized names.
Serialized names occur only in the encoded form.
MDL entity | Decoded name | Encoded name |
---|---|---|
module with builtins | — | mdl::%3Cbuiltins%3E |
user module | — | mdl::foo |
MDLE module (Linux) | — | mdle::bar.mdle (4) |
MDLE module (Windows) | — | mdle::bar.mdle (5) |
builtin function | — | mdl::operator+(float,float) |
builtin function, affected by encoding | — | mdl::operator%3C%3C(int,int) |
builtin template-like function | — | mdl::operator%3F(bool,%3C0%3E,%3C0%3E)<int> |
user function | — | mdl::foo::my_func(color) |
user function, module name affected by encoding | — | mdl::foo%2Cbar::my_func(::foo%2Cbar::my_enum) |
user material | — | mdl::foo::my_mat(color) |
(4) With an MDLE callback that strips all directory components during serialization (see mi::neuraylib::IMdle_serialization_callback).
(5) With an MDLE callback that strips all drive and directory components during serialization (see mi::neuraylib::IMdle_serialization_callback).
For each exported struct type function definitions for its constructors are created in the DB. There is a default constructor and a so-called elemental constructor which has a parameter for each field of the struct. The name of these constructors is the name of the struct type including the signature.
"mod_struct"
creates the following function definitions:"mdl::mod_struct::Foo()"
,"mdl::mod_struct::Foo(int,float)"
, and"param_int"
of type mi::neuraylib::IType_int and a parameter "param_float"
of type mi::neuraylib::IType_float. Both function definitions have the return type mi::neuraylib::IType_struct with name "::mod_struct::Foo"
.In addition, for each exported struct type, and for each of its fields, a function definition for the corresponding member selection operator is created in the DB. The name of that function definition is obtained by concatenating the name of the struct type with the name of the field with an intervening dot, e.g., "foo.param_int"
. The function definition has a single parameter "s"
of the struct type and the corresponding field type as return type.
"mod_struct"
creates the two function definitions named "mdl::mod_struct::Foo.param_int(::mod_struct::Foo)"
and "mdl::mod_struct::Foo.param_float(::mod_struct::Foo)"
to represent the member selection operators "Foo.param_int"
and "Foo.param_float"
. The function definitions have a single parameter "s"
of type "mdl::mod_struct::Foo"
and return type mi::neuraylib::IType_int and mi::neuraylib::IType_float, respectively.In contrast to struct types which are explicitly declared there are infinitely many array types (considering pairs of element type and array length). Deferred-sized arrays make the situation even more complicated. Each of these array types would have its own constructor and index operator. Therefore, template-like functions definitions are used in the context of arrays to satisfy this need. See the next section for details
Usually, function definitions have a fixed set of parameter types and a fixed return type. Exceptions of this rule are the following six function definitions which rather have the character of template functions with generic parameter and/or return types.
The MDL and DB names of these function definitions use "<0>"
or "T"
to indicate such a generic parameter or return type. When querying the actual type, mi::neuraylib::IType_int (arbitrary choice) is returned for lack of a better alternative.
When creating function calls from such template-like function definitions, the parameter and return types are fixed, i.e., the function call itself has concrete parameter and return types as usual, and has no template-like behavior as the definition from which it was created. This implies that, for example, after creating a ternary operator on floats, you cannot set its arguments to expressions of a different type than float (this would require creation of another function call with the desired parameter types).
Template-like functions are those functions for which serialized name and DB name differ (see Naming scheme for MDL elements).
More details about the six different template-like function definitions follow.
Semantic: mi::neuraylib::IFunction_definition::DS_INTRINSIC_DAG_ARRAY_CONSTRUCTOR
DB name: "mdl::T[](...)"
MDL name: "T[](...)"
Serialized named (example): "mdl::T[](...)<int,42>"
The following requirements apply when creating function calls of the array constructor:
The suffix for the serialized name has two arguments, the type name of the element type, and the size of the array.
Semantic: mi::neuraylib::IFunction_definition::DS_INTRINSIC_DAG_ARRAY_LENGTH
DB name: "mdl::operator_len(%3C0%3E[])"
MDL name): "operator_len(%3C0%3E[])"
Serialized name (example): "operator_len(%3C0%3E[])<float[42]>"
The following requirements apply when creating function calls of the array length operator:
"a"
of type mi::neuraylib::IType_array.The suffix for the serialized name has one argument, the type name of the array.
Semantic: mi::neuraylib::IFunction_definition::DS_ARRAY_INDEX
DB name: "mdl::operator[](%3C0%3E[],int)"
MDL name: "operator[](%3C0%3E[],int)"
Serialized name (example): "operator[](%3C0%3E[],int)<float[42]>"
Despite its name, the array index operator can also be used on vectors and matrices.
The following requirements apply when creating function calls of the array index operator:
"a"
and "i"
, respectively,"a"
is of type mi::neuraylib::IType_array, mi::neuraylib::IType_vector, or mi::neuraylib::IType_matrix, and"i"
is of type mi::neuraylib::IType_int.The suffix for the serialized name has one argument, the type name of the array, vector, or matrix.
Semantic: mi::neuraylib::IFunction_definition::DS_TERNARY
DB name: "mdl::operator%3F(bool,%3C0%3E,%3C0%3E)"
MDL name: "operator%3F(bool,%3C0%3E,%3C0%3E)"
Serialized name (example): "operator%3F(bool,%3C0%3E,%3C0%3E)<float>"
The following requirements apply when creating function calls of the ternary operator:
"cond"
, "true_exp"
, and "false_exp"
, respectively,"cond"
is of type mi::neuraylib::IType_bool, andThe suffix for the serialized name has one argument, the type name of the "true_exp"
expression (which is equal to the type name of the "false_exp"
expression).
Semantic: mi::neuraylib::IFunction_definition::DS_CAST
DB name: "mdl::operator_cast(%3C0%3E)"
MDL name: "operator_cast(%3C0%3E)"
Serialized name (example): "operator_cast(%3C0%3E)<::foo::my_enum,::bar::my_enum>"
The following requirements apply when creating function calls of the cast operator:
"cast"
and "cast_return"
, respectively,"cast"
is of an arbitrary type (this is the intended argument of the function call),"cast_return"
specifies the return type of the function call (no frequency qualifiers; the expression itself is not used), and"cast"
and "cast_return"
are compatible.The suffix for the serialized name has two arguments, the type name of the "cast"
expression, followed by the type name of the "cast_return"
expression.
See also mi::neuraylib::IExpression_factory::create_cast().
The decl_cast
operator is used to express casts between different struct types from the same struct category.
Semantic: mi::neuraylib::IFunction_definition::DS_INTRINSIC_DAG_DECL_CAST
DB name: "mdl::operator_decl_cast(%3C0%3E)"
MDL name: "operator_decl_cast(%3C0%3E)"
Serialized name (example): "operator_decl_cast(%3C0%3E)<::foo::some_material_type,::foo::another_material_type>"
The following requirements apply when creating function calls of the decl_cast operator:
"cast"
and "cast_return"
, respectively,"cast"
is a struct type with a struct category (this is the intended argument of the function call),"cast_return"
specifies the return type of the function call (no frequency qualifiers; the expression itself is not used), and"cast"
and "cast_return"
are struct types from the same struct category.The suffix for the serialized name has two arguments, the type name of the "cast"
expression, followed by the type name of the "cast_return"
expression.
The opacity of a compiled material.
See mi::neuraylib::ICompiled_material::get_opacity() and mi::neuraylib::ICompiled_material::get_surface_opacity().
Enumerator | |
---|---|
OPACITY_OPAQUE | The material is opaque. |
OPACITY_TRANSPARENT | The material is transparent. |
OPACITY_UNKNOWN | The opacity of the material is unknown, e.g., because it depends on parameters. |
Material slots identify parts of a compiled material.