Introduction
To import a custom Material definition (read ExchangeMapper Material Definition Mapper Manual), into your own custom Cinema 4D material, the next interfaces should be implemented according to the specific needs:
One material definition can have multiple maxon::material::MaterialImportInterface or maxon::nodes::NodeMaterialImportInterface implementations describing how the import process takes place.
It is up to the requirements to create the material definition and import the data to choose which MaterialImportRef/MaterialNodeImportRef will perform the material creation.
It is also possible to create multiple material types by using multiples MaterialImportRef/MaterialNodeImportRef.
The import process does not provide an automatic baking functionality if a given material description is not handled by the maxon::material::MaterialImportInterface or maxon::nodes::NodeMaterialImportInterface implementations.
This ensures that, the 3-rd party developer should carefully considers what an unknown material description could mean for his material type since he should know and, probably, generate the default values.
However, one may be interested to explicitly convert the given material description to another one that he already knows. For more information read ExchangeMapper Material Definition Mapper Manual.
MaterialImportInterface
A maxon::material::MaterialImportInterface can be called at any time: from a SceneLoaderData but also from a regular CommandData or anything else.
A maxon::material::MaterialImportInterface provides a CreateMaterial() methods that need to be implemented.
It's important to registers the maxon::Class object representing the current maxon::material::MaterialImportInterface implementation into the maxon::material::MaterialImporters registry. Because of this, a SceneLoaderData can expose to the user all possible import solutions available. The following code is an implementation example:
{
importDescription.
_class = SimpleMaterialImport::GetClass();
g_materialImportRegistration = maxon::material::MaterialImporters::Register(SimpleMaterialImport::GetDescriptor().GetId(), std::move(importDescription))
iferr_return;
}
void SimpleMaterialImport::Free()
{
}
return OK
Definition: apibase.h:2771
String LoadResourceString(const STRID &identifier, const ARGUMENTS &... args)
Loads the string 'identifier' from the resource and format with the passed parameters.
Definition: string.h:2305
#define MAXON_COMPONENT_OBJECT_REGISTER(C,...)
Definition: objectbase.h:2490
GenericDataTemplate< false > GenericData
Definition: genericdata.h:223
#define iferr_scope
Definition: resultbase.h:1396
#define iferr_return
Definition: resultbase.h:1531
Definition: materialimport.h:105
String _name
Definition: materialimport.h:106
Class< MaterialImportRef > _class
Definition: materialimport.h:107
The maxon::material::MaterialImportInterface::CreateMaterial() returns a pointer to a BaseMaterial.
The ownership of this BaseMaterial should be properly managed: whilst it's up to the maxon::material::MaterialImportInterface to allocate the BaseMaterial, the importer is responsible to insert it into the document (and transfer the ownership to it) or either to free the allocated BaseMaterial.
This method is called during the import process with the material definition (maxon::material::MaterialExchangeData) and only for context purpose, the BaseDocument the BaseMaterial should be created into and a maxon::DataDictionary containing the import configuration.
The following code is an implementation using the SimpleMaterial from Cinema 4D SDK as the target of the import process.
{
const Int32 ID_SIMPLEMAT = 1001164;
const Int32 SIMPLEMATERIAL_COLOR = 1000;
BaseMaterial* simpleMaterial = (BaseMaterial*)(materialPlugin->Alloc(ID_SIMPLEMAT));
Vector simpleMaterialColor = simpleMaterial->GetDataInstanceRef().GetVector(SIMPLEMATERIAL_COLOR);
if (materialData._materialTypeId ==
maxon::
MATERIAL::PORTBUNDLE::STANDARDSURFACE::GetId())
{
simpleMaterialColor = baseColor.
_value.GetVector();
}
else if (materialData.
_materialTypeId == maxon::MATERIAL::PORTBUNDLE::FBXSURFACELAMBERT::GetId() || materialData.
_materialTypeId == maxon::MATERIAL::PORTBUNDLE::FBXSURFACEPHONG::GetId())
{
simpleMaterialColor = diffuse.
_value.GetVector();
}
else
{
maxon::Id targetMaterialDefinition = maxon::MATERIAL::PORTBUNDLE::STANDARDSURFACE::GetId();
{
if (
mapping._source != srcMaterialDefinition)
continue;
if (
mapping._target != targetMaterialDefinition)
continue;
unknowToStandardMappingDescription =
mapping;
break;
}
if (unknowToStandardMappingDescription.
_source == srcMaterialDefinition && unknowToStandardMappingDescription.
_target == targetMaterialDefinition)
{
maxon::material::MaterialMappingRef unknowToStandardMapping = unknowToStandardMappingDescription.
_class.Create()
iferr_return;
}
}
simpleMaterial->GetDataInstanceRef().SetVector(SIMPLEMATERIAL_COLOR, simpleMaterialColor);
return simpleMaterial;
}
MATERIAL
Definition: asset_browser.h:5
Definition: apibaseid.h:243
static MAXON_METHOD Result< DataDictionary > LoadDefaults(const Id &materialType)
Py_ssize_t PyObject * mapping
Definition: unicodeobject.h:919
#define CheckState(condition,...)
Definition: errorbase.h:510
BaseMaterial * CreateMaterial(BaseList2D *const asset, Int32 graphIndex, SUBSTANCE_MATERIAL_MODE mode)
BasePlugin * FindPlugin(Int32 id, PLUGINTYPE type)
maxon::Int32 Int32
Definition: ge_sys_math.h:51
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:140
The maxon namespace contains all declarations of the Maxon API.
Definition: autoweight.h:21
Definition: materialparameter.h:191
DataDictionary _parameters
Definition: materialparameter.h:210
Id _materialTypeId
Definition: materialparameter.h:203
HashMap< Id, Data > _textures
Definition: materialparameter.h:219
Definition: materialmapping.h:119
Id _source
Definition: materialmapping.h:120
Id _target
Definition: materialmapping.h:121
Class< MaterialMappingRef > _class
Definition: materialmapping.h:122
Definition: materialparameter.h:271
TYPE _value
Definition: materialparameter.h:286
NodeMaterialImportInterface
A maxon::nodes::NodeMaterialImportInterface can be called at any time, e.g. from a SceneLoaderData but also from a regular CommandData or anything else.
A maxon::nodes::NodeMaterialImportInterface provides an Import method that needs to be implemented.
This method is called during the import process with a node graph to be filled (NodesGraphModelRef) with the material definition (maxon::material::MaterialExchangeData) and only for context purpose, the document. It's up to the importer to decide what to do:
- it can read attribute values directly from the material description and fed the data directly within the end node of the graph or
- it can create an "import" node that represents the material description, then link the value from this "import" node to the end node of the graph to have the raw data exposed to the user.
To help in the process of the "import" node the maxon::nodes::NodeMaterialImportHelperInterface can be used to creates attributes that will be exposed as a node in the node graph.
{
{
for (const auto& textureEntry : textureReferences)
{
const maxon::Id& textureId = textureEntry.GetKey();
const maxon::Data& textureData = textureEntry.GetValue();
if (textureType == maxon::GetDataType<maxon::material::ImageReference>())
{
}
else if (textureType == maxon::GetDataType<maxon::material::SubstanceReference>())
{
}
else
{
DiagnosticOutput(
"Parameter '@' has texture reference of unknown type '@'.", textureId, textureType);
}
}
}
{
helper.AddParameters(materialData._parameters)
iferr_return;
const
maxon::nodes::NodeMaterialImportHelperInterface::GroupNodeData groupData = helper.Finalize()
iferr_return;
}
}
BaseList2D* ExampleNodeMaterialImport::FindSubstanceAsset(BaseDocument& baseDocument, const String& assetName)
{
AutoAlloc<AtomArray> substances;
if (substances == nullptr)
return nullptr;
const Bool onlySelected =
false;
{
BaseList2D* asset =
static_cast<BaseList2D*
>(substances->GetIndex(
index));
if (asset == nullptr)
continue;
if (asset->GetName() == assetName)
return asset;
}
return nullptr;
}
#define Import(a0, a1, a2, a3, a4, a5)
Definition: Python-ast.h:536
Definition: datatypebase.h:1235
Result< typename std::conditional< GetCollectionKind< T >::value==COLLECTION_KIND::ARRAY||std::is_void_v< T >, T, std::add_lvalue_reference_t< const T > >::type > Get() const
Definition: datatypebase.h:1395
const DataType & GetType() const
Definition: datatypebase.h:1288
Definition: datatypebase.h:770
static MAXON_METHOD Result< NodeMaterialImportHelperRef > CreateAndInitialize(NodesGraphModelRef &graph, const Id &materialType)
Py_ssize_t * index
Definition: abstract.h:374
OK
User has selected a font.
Definition: customgui_fontchooser.h:0
bool Bool
boolean type, possible values are only false/true, 8 bit
Definition: apibase.h:180
#define MAXON_SCOPE
Definition: apibase.h:2922
int32_t Int32
32 bit signed integer datatype.
Definition: apibase.h:175
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:170
void GetSubstances(BaseDocument *const doc, AtomArray *arr, Bool onlySelected)
Defines a reference to an image file to represent a material parameter.
Definition: materialparameter.h:49
Url _absolutePath
Definition: materialparameter.h:56
Definition: materialparameter.h:75
String _assetName
Definition: materialparameter.h:90
Url _absolutePath
Definition: materialparameter.h:82
String _outputChannelName
The name of the substance output according to the GetSubstanceOutput query of the C4D Substance API.
Definition: materialparameter.h:95
Further Reading