MDL SDK API nvidia_logo_transpbg.gif Up
Example for MDL Modules
[Previous] [Up] [Next]

This example loads an MDL module and inspects it contents.

New Topics

  • Configuration of the MDL SDK
  • Loading of MDL modules
  • Enumerating the contents of MDL modules
  • Inspecting the parameters of material and function definitions

Detailed Description

Configuration of the MDL SDK


In order to allow the the MDL SDK to locate MDL modules and its resources in the file system it is necessary to configure the MDL module search path. This is done by calling mi::neuraylib::IMdl_configuration::add_mdl_path().

Our example module ::nvidia::sdk_examples::tutorials makes use of textures. The support for image formats in the the MDL SDK is provided by image plugins, which have to be loaded explicitly via mi::neuraylib::IPlugin_configuration::load_plugin_library().

In this and most other examples the configuration is done within the utility function configure(). Here, we set the module search path to the MDL directory shipped with the examples. We also load the OpenImageIO plugin which comes with the the MDL SDK and is capable of handling .png files.

Loading of MDL modules


MDL modules are loaded with the method mi::neuraylib::IMdl_impexp_api::load_module(). Note that this method expects the module name, not the name of the file containing the module. To find the corresponding file it is necessary to configure the module search path as described above.

Enumerating the contents of MDL modules


The mi::neuraylib::IModule interface offers various methods related to metadata, like the name of the module, or the name of the file it was loaded from. Furthermore, it offers methods to enumerate the material and function definitions contained in the module. It also allows to enumerate all modules that have been (directly) imported by that module. Imported modules will be automatically loaded (if not already loaded before).

Inspecting the parameters of material and function definitions


MDL materials and functions (as found in a .mdl file) are represented in the MDL SDK API by the interface mi::neuraylib::IFunction_definition. Similar to the module interface thi interface offers various methods related to metadata, like the name of the definition, or the name of the containing module. Important methods are those that provide details about the parameters, like their names, types, and the values of defaults (if present).

In this example we simply dump the parameter information for the first material and function definition. The textual representation of the default values is generated by the method mi::neuraylib::IExpression_factory::dump().

Enumerating resources required by a module


The example also demonstrates the iteration of required resources. After reading the number of resources, we can iterate them and get the database name, the mdl file path, and the resource type. Based on the latter, it is possible to fetch the resolved resource path that points to the file on the current system. In case the resource could not be resolved, the database name will be NULL. However, the MDL file path will still point to the missing resource.

Example Source

Source Code Location: examples/mdl_sdk/modules/example_modules.cpp

/******************************************************************************
* Copyright 2023 NVIDIA Corporation. All rights reserved.
*****************************************************************************/
// examples/mdl_sdk/modules/example_modules.cpp
//
// Loads an MDL module and inspects it contents.
#include <iostream>
#include <string>
#include "example_shared.h"
const char* material_definition_name
= "mdl::nvidia::sdk_examples::tutorials::example_material(color,float)";
const char* function_definition_name
= "mdl::nvidia::sdk_examples::tutorials::example_function(color,float)";
// Utility function to dump the parameters of a material or function definition.
template <class T>
void dump_definition(
const T* definition,
mi::Size depth,
std::ostream& s)
{
mdl_factory->create_type_factory( transaction));
mdl_factory->create_expression_factory( transaction));
mi::Size count = definition->get_parameter_count();
mi::base::Handle<const mi::neuraylib::IType_list> types( definition->get_parameter_types());
mi::base::Handle<const mi::neuraylib::IExpression_list> defaults( definition->get_defaults());
for( mi::Size index = 0; index < count; index++) {
mi::base::Handle<const mi::neuraylib::IType> type( types->get_type( index));
mi::base::Handle<const mi::IString> type_text( type_factory->dump( type.get(), depth+1));
std::string name = definition->get_parameter_name( index);
s << " parameter " << type_text->get_c_str() << " " << name;
defaults->get_expression( name.c_str()));
if( default_.is_valid_interface()) {
expression_factory->dump( default_.get(), 0, depth+1));
s << ", default = " << default_text->get_c_str() << std::endl;
} else {
s << " (no default)" << std::endl;
}
}
mi::Size temporary_count = definition->get_temporary_count();
for( mi::Size i = 0; i < temporary_count; ++i) {
mi::base::Handle<const mi::neuraylib::IExpression> temporary( definition->get_temporary( i));
std::stringstream name;
name << i;
expression_factory->dump( temporary.get(), name.str().c_str(), 1));
s << " temporary " << result->get_c_str() << std::endl;
}
mi::base::Handle<const mi::IString> result( expression_factory->dump( body.get(), 0, 1));
if( result)
s << " body " << result->get_c_str() << std::endl;
else
s << " body not available for this function" << std::endl;
s << std::endl;
}
// Loads an MDL module and inspects it contents.
void load_module( mi::neuraylib::INeuray* neuray)
{
// Access the database and create a transaction.
mi::base::Handle<mi::neuraylib::IScope> scope( database->get_global_scope());
mi::base::Handle<mi::neuraylib::ITransaction> transaction( scope->create_transaction());
{
mdl_factory->create_execution_context());
// Load the module "tutorials".
check_success(mdl_impexp_api->load_module(
transaction.get(), "::nvidia::sdk_examples::tutorials", context.get()) >= 0);
print_messages( context.get());
// Access the module by its name. The name to be used here is the MDL name of the module
// ("example") plus the "mdl::" prefix.
transaction->access<mi::neuraylib::IModule>( "mdl::nvidia::sdk_examples::tutorials"));
check_success( module.is_valid_interface());
// Print the module name and the file name it was loaded from.
std::cout << "Loaded file " << module->get_filename() << std::endl;
std::cout << "Found module " << module->get_mdl_name() << std::endl;
std::cout << std::endl;
// Dump imported modules.
mi::Size module_count = module->get_import_count();
std::cout << "The module imports the following modules:" << std::endl;
for( mi::Size i = 0; i < module_count; i++)
std::cout << " " << module->get_import( i) << std::endl;
std::cout << std::endl;
// Dump exported types.
mdl_factory->create_type_factory( transaction.get()));
std::cout << "The module contains the following types: " << std::endl;
for( mi::Size i = 0; i < types->get_size(); ++i) {
mi::base::Handle<const mi::IString> result( type_factory->dump( type.get(), 1));
std::cout << " " << result->get_c_str() << std::endl;
}
std::cout << std::endl;
// Dump exported constants.
mdl_factory->create_value_factory( transaction.get()));
mi::base::Handle<const mi::neuraylib::IValue_list> constants( module->get_constants());
std::cout << "The module contains the following constants: " << std::endl;
for( mi::Size i = 0; i < constants->get_size(); ++i) {
const char* name = constants->get_name( i);
mi::base::Handle<const mi::neuraylib::IValue> constant( constants->get_value( i));
mi::base::Handle<const mi::IString> result( value_factory->dump( constant.get(), 0, 1));
std::cout << " " << name << " = " << result->get_c_str() << std::endl;
}
std::cout << std::endl;
// Dump function definitions of the module.
mi::Size function_count = module->get_function_count();
std::cout << "The module contains the following function definitions:" << std::endl;
for( mi::Size i = 0; i < function_count; i++)
std::cout << " " << module->get_function( i) << std::endl;
std::cout << std::endl;
// Dump material definitions of the module.
mi::Size material_count = module->get_material_count();
std::cout << "The module contains the following material definitions:" << std::endl;
for( mi::Size i = 0; i < material_count; i++)
std::cout << " " << module->get_material( i) << std::endl;
std::cout << std::endl;
// Dump a function definition from the module.
std::cout << "Dumping function definition \"" << function_definition_name << "\":"
<< std::endl;
transaction->access<mi::neuraylib::IFunction_definition>( function_definition_name));
dump_definition(
transaction.get(), mdl_factory.get(), function_definition.get(), 1, std::cout);
// Dump a material definition from the module.
std::cout << "Dumping material definition \"" << material_definition_name << "\":"
<< std::endl;
transaction->access<mi::neuraylib::IFunction_definition>( material_definition_name));
dump_definition(
transaction.get(), mdl_factory.get(), material_definition.get(), 1, std::cout);
// Dump the resources referenced by this module
std::cout << "Dumping resources of this module: \n";
for( mi::Size r = 0, rn = module->get_resources_count(); r < rn; ++r)
{
module->get_resource( r));
const char* db_name = resource->get_value();
const char* mdl_file_path = resource->get_file_path();
if( db_name == nullptr)
{
// resource is either not used and therefore has not been loaded or
// could not be found.
std::cout << " db_name: none" << std::endl;
std::cout << " mdl_file_path: " << mdl_file_path << std::endl
<< std::endl;
continue;
}
std::cout << " db_name: " << db_name << std::endl;
std::cout << " mdl_file_path: " << mdl_file_path << std::endl;
resource->get_type());
switch( type->get_kind())
{
{
transaction->access<mi::neuraylib::ITexture>( db_name));
if( texture)
{
transaction->access<mi::neuraylib::IImage>( texture->get_image()));
for( mi::Size f = 0, fn = image->get_length(); f < fn; ++f)
for( mi::Size t = 0, tn = image->get_frame_length( f); t < tn; ++t)
{
const char* resolved_file_path = image->get_filename( f, t);
std::cout << " resolved_file_path[" << f << "," << t << "]: "
<< resolved_file_path << std::endl;
}
}
break;
}
{
transaction->access<mi::neuraylib::ILightprofile>( db_name));
if( light_profile)
{
const char* resolved_file_path = light_profile->get_filename();
std::cout << " resolved_file_path: " << resolved_file_path << std::endl;
}
break;
}
{
transaction->access<mi::neuraylib::IBsdf_measurement>( db_name));
if( mbsdf)
{
const char* resolved_file_path = mbsdf->get_filename();
std::cout << " resolved_file_path: " << resolved_file_path << std::endl;
}
break;
}
default:
break;
}
std::cout << std::endl;
}
}
// All transactions need to get committed.
transaction->commit();
}
int MAIN_UTF8( int /*argc*/, char* /*argv*/[])
{
// Access the MDL SDK
mi::base::Handle<mi::neuraylib::INeuray> neuray(mi::examples::mdl::load_and_get_ineuray());
if (!neuray.is_valid_interface())
exit_failure("Failed to load the SDK.");
// Configure the MDL SDK
if (!mi::examples::mdl::configure(neuray.get()))
exit_failure("Failed to initialize the SDK.");
// Start the MDL SDK
mi::Sint32 ret = neuray->start();
if (ret != 0)
exit_failure("Failed to initialize the SDK. Result code: %d", ret);
// Load an MDL module and dump its contents
load_module( neuray.get());
// Shut down the MDL SDK
if (neuray->shutdown() != 0)
exit_failure("Failed to shutdown the SDK.");
// Unload the MDL SDK
neuray = nullptr;
if (!mi::examples::mdl::unload())
exit_failure("Failed to unload the SDK.");
exit_success();
}
// Convert command line arguments to UTF8 on Windows
COMMANDLINE_TO_UTF8
Handle class template for interfaces, automatizing the lifetime control via reference counting.
Definition: handle.h:113
A scene element that stores measured BSDF data.
Definition: ibsdf_measurement.h:39
This interface is used to interact with the distributed database.
Definition: idatabase.h:293
This interface represents a function definition.
Definition: ifunction_definition.h:44
This interface represents a pixel image file.
Definition: iimage.h:65
This interface represents light profiles.
Definition: ilightprofile.h:73
Factory for various MDL interfaces and functions.
Definition: imdl_factory.h:53
virtual IMdl_execution_context * create_execution_context()=0
Creates an execution context.
virtual IType_factory * create_type_factory(ITransaction *transaction)=0
Returns an MDL type factory for the given transaction.
virtual IExpression_factory * create_expression_factory(ITransaction *transaction)=0
Returns an MDL expression factory for the given transaction.
virtual IValue_factory * create_value_factory(ITransaction *transaction)=0
Returns an MDL value factory for the given transaction.
API component for MDL related import and export operations.
Definition: imdl_impexp_api.h:42
This interface represents an MDL module.
Definition: imodule.h:611
This is an object representing the MDL SDK library.
Definition: ineuray.h:44
virtual Sint32 shutdown(bool blocking=true)=0
Shuts down the library.
virtual base::IInterface * get_api_component(const base::Uuid &uuid) const =0
Returns an API component from the MDL SDK API.
virtual Sint32 start(bool blocking=true)=0
Starts the operation of the MDL SDK library.
Textures add image processing options to images.
Definition: itexture.h:68
A transaction provides a consistent view on the database.
Definition: itransaction.h:81
virtual const base::IInterface * access(const char *name)=0
Retrieves an element from the database.
virtual Sint32 commit()=0
Commits the transaction.
@ TK_TEXTURE
A texture type. See mi::neuraylib::IType_texture.
Definition: itype.h:80
@ TK_BSDF_MEASUREMENT
The bsdf_measurement type. See mi::neuraylib::IType_bsdf_measurement.
Definition: itype.h:84
@ TK_LIGHT_PROFILE
The light_profile type. See mi::neuraylib::IType_light_profile.
Definition: itype.h:82
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
signed int Sint32
32-bit signed integer.
Definition: types.h:46
[Previous] [Up] [Next]