ExchangeMapper Material Export Manual

Introduction

To export a custom Material definition (read ExchangeMapper Material Definition Manual), from your own custom Cinema 4D material, the next interfaces need to be implemented according to your need:

One material can have multiple maxon::material::MaterialExportInterface or maxon::nodes::NodeMaterialExportInterface implementations describing how the export process will work.

The export process provides automatic baking if a given material description is not handled by the maxon::material::MaterialExportInterface or maxon::nodes::NodeMaterialExportInterface implementations through the maxon::NODESPACE::EXCHANGE::BUNDLE::VIEWPORTMATERIAL material description.

As an example, if an FBX is exported but the implemented exporter only handles a VIEWPORTMATERIAL material definition for the given material, the VIEWPORTMATERIAL material description provided by the exporter will be mapped to an FBX material description automatically.
However, it's relevant to remind that this translation is a lossy translation, with data being sacrificed.
For better handling, it's instead suggested to directly output an FBX material definition. For more information read ExchangeMapper Material Definition Manual.

Note
Within the material export implementation, it is recommended monitoring the thread cancellation state when executing time-consuming operations (e.g. baking) to react immediately upon user aborting an export process.

 MaterialExportInterface

maxon::material::MaterialExportInterface can be called at any time, e.g. from a SceneLoaderData but also from a regular CommandData or anything else.

maxon::material::MaterialExportInterface provides few methods:

All MaterialExportInterface shall be registered using a maxon::material::MaterialExportDescription into the maxon::material::MaterialExporters registry.

maxon::material::MaterialExportDescription links a given Cinema API Plugin ID to a maxon::material::MaterialExportRef.

Example of an implementation using the SimpleMaterial from the Cinema 4D SDK as the source of the export process.

maxon::Result<void> SimpleMaterialExport::Initialize(const BaseMaterial& baseMaterial, const maxon::DataDictionary& config)
{
_baseMaterial = &baseMaterial;
maxon::material::MaterialTypesMap materialTypes = config.Get(maxon::material::EXPORT::CONFIG::MATERIALTYPESWITHSUPPORT) iferr_return;
// We only support Standard Surface in this example.
CheckArgument(materialTypes.Contains(maxon::MATERIAL::PORTBUNDLE::STANDARDSURFACE::GetId()) == true);
return maxon::OK;
}
{
result.first = maxon::MATERIAL::PORTBUNDLE::STANDARDSURFACE::GetId();
result.second = maxon::material::ParameterStorageInterface::LoadDefaults(maxon::MATERIAL::PORTBUNDLE::STANDARDSURFACE::GetId()) iferr_return;
if (_baseMaterial != nullptr)
{
const Int32 SIMPLEMATERIAL_COLOR = 1000;
const maxon::Color simpleMaterialColor = _baseMaterial->GetDataInstanceRef().GetVector(SIMPLEMATERIAL_COLOR).GetColor();
maxon::material::ParameterStorageInterface::Insert(result.second, maxon::MATERIAL::PORTBUNDLE::STANDARDSURFACE::BASE_COLOR, simpleMaterialColor, true, 0) iferr_return;
}
return result;
}
maxon::Result<maxon::HashMap<maxon::Id, maxon::Data>> SimpleMaterialExport::GetTextures(const maxon::HashSet<maxon::Id>& texturedChannels)
{
// No textures to declare.
return textures;
}
// The Registration Process
static maxon::GenericData g_materialExportRegistration;
maxon::Result<void> SimpleMaterialExport::Register()
{
const Int32 ID_SIMPLEMAT = 1001164;
description._type = ID_SIMPLEMAT;
description._class = SimpleMaterialExport::GetClass();
g_materialExportRegistration = maxon::material::MaterialExporters::Register(SimpleMaterialExport::GetDescriptor().GetId(), std::move(description)) iferr_return;
return maxon::OK;
}
void SimpleMaterialExport::Free()
{
g_materialExportRegistration = maxon::GenericData();
}
MAXON_COMPONENT_OBJECT_REGISTER(SimpleMaterialExport, "net.maxonsdk.doc_cpp.class.simplematerialexport");
Definition: hashmap.h:1115
MAXON_ATTRIBUTE_FORCE_INLINE Bool Contains(typename ByValueParam< KEYTYPE >::type key) const
Definition: collection.h:1351
Definition: tuple.h:611
static Result< void > Insert(DataDictionary &parameters, KEY &&id, T &&value, Bool isConstant, UInt dynamicTimestamp)
Definition: materialparameter.h:371
static MAXON_METHOD Result< DataDictionary > LoadDefaults(const Id &materialType)
PyObject PyObject * result
Definition: abstract.h:43
int32_t Int32
32 bit signed integer datatype.
Definition: apibase.h:175
return OK
Definition: apibase.h:2771
#define CheckArgument(condition,...)
Definition: errorbase.h:486
#define MAXON_COMPONENT_OBJECT_REGISTER(C,...)
Definition: objectbase.h:2490
The maxon namespace contains all declarations of the Maxon API.
Definition: autoweight.h:21
GenericDataTemplate< false > GenericData
Definition: genericdata.h:223
#define iferr_scope
Definition: resultbase.h:1396
#define iferr_return
Definition: resultbase.h:1531
constexpr const Vec3< T, STRIDE > & GetVector() const
Reinterprets the color as vector.
Definition: col.h:388
Definition: materialexport.h:178
Class< MaterialExportRef > _class
Definition: materialexport.h:180
Int32 _type
Definition: materialexport.h:179

 NodeMaterialExportInterface

maxon::nodes::NodeMaterialExportInterface can be called at any time, e.g. from a SceneLoaderData but also from a regular CommandData or anything else.

maxon::nodes::NodeMaterialExportInterface  provides few methods:

To register a supported material definition, the maxon::nodes::NODESPACE::MATERIALEXCHANGEBUNDLEIDS attribute of the node space shall be filled with a maxon::BaseArray of material bundle maxon::Id.

maxon::BaseArray<maxon::Id> materialExchangeBundleIds;
materialExchangeBundleIds.Append(maxon::NODESPACE::EXCHANGE::BUNDLE::VIEWPORTMATERIAL::GetId()) iferr_return;
nodeSpaceData.Set(maxon::nodes::NODESPACE::MATERIALEXCHANGEBUNDLEIDS, std::move(materialExchangeBundleIds)) iferr_return;
MAXON_ATTRIBUTE_FORCE_INLINE ResultRef< T > Append(ARG &&x)
Appends a new element at the end of the array and constructs it using the forwarded value.
Definition: basearray.h:626

To register the custom exporter, the maxon::nodes::NODESPACE::MATERIALEXCHANGECLASS attribute of the node space shall be filled with the maxon::nodes::NodeMaterialExportInterface maxon::Class object.

// nodeSpaceData.Set(maxon::nodes::NODESPACE::MATERIALEXCHANGECLASS, YourMaterialNodeExportInterfaceImplementation::GetClass()) iferr_return;

If no exporter is defined for a given node space, a fall-back is performed by the maxon::nodes::MaterialExchangeInterface to create a textured material of type maxon::NODESPACE::EXCHANGE::BUNDLE::VIEWPORTMATERIAL.

Further Reading