Hi @rajeev,
This is going to get a little complicated. Part of the complication is due to historical reasons and the way the material system has evolved over the last decade or two. I’ll try to explain it as simply as possible.
First, when I said it’s best to avoid ON_Material
I forgot that it’s actually unavoidable when you want to assign a render material to a ModelGeometryComponent
. This is because such an assignment requires the objects to be connected together by the use of an ON_Material
since ModelGeometryComponent
existed long before ON_RenderMaterial
did and the attributes of the model component uses the component index of the ON_Material
to identify the material.
The ON_Material
is connected to the ON_RenderMaterial
by setting two values: the unique ID of the ON_RenderMaterial
and a plug-in ID. It’s necessary for the plug-in ID to be set to the ‘universal’ value (which is all 9s) because it doesn’t belong to any 3rd-party plug-in (it belongs to the RDK subsystem of Rhino). The ON_Material
has a SetRdkMaterialInstanceId()
method that sets the render material’s ID and a SetMaterialPlugInId()
method that sets the plug-in ID.
In summary, ModelGeometryComponent
attributes uses the material index of an ON_Material
which in turn indicates which ON_RenderMaterial
to use by specifying its unique ID.
Below is an example of how to create a new render material and assign it to the first ModelGeometryComponent
in the model. First an ON_Material
is added to the model, its values are set and then we just get the first ON_ModelGeometryComponent
in the model and use its attributes to assign the material. The ON_Material
is given an index of zero as I assume it’s the first one being added. You might need to modify that.
About the UUIDs: this conversation has highlighted an oversight. These UUIDs were originally defined in the RDK and have not been exposed to users of ‘plain’ OpenNURBS. I will need to fix that by moving them into opennurbs_render_content.h
. For now, just use the UUIDs below. I will try to fix this in the next day or so.
bool CreateAndAssignMaterial(ONX_Model& model)
{
// Create the render material, set its properties and add it to the model.
ON_RenderMaterial render_mat;
const ON_UUID uuidCustomMaterialType = { 0xba51c000, 0xba51, 0xc000,
{ 0xba, 0x51, 0xc0, 0xba, 0x51, 0xc0, 0x00, 0x00 } };
render_mat.SetTypeId(uuidCustomMaterialType);
render_mat.SetName(L"My Material");
const ON_4fColor col(1.0f, 0.5f, 0.5f, 1.0f);
render_mat.SetParameter(ON_MATERIAL_DIFFUSE, ON_XMLVariant(col));
model.AddModelComponent(render_mat);
// Create an ON_Material to use for the render material assignment and add it to the model.
ON_Material mat;
mat.SetIndex(0); // Assume first material.
mat.SetRdkMaterialInstanceId(render_mat.Id());
const ON_UUID uuidUniversal = { 0x99999999, 0x9999, 0x9999,
{ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99 } };
mat.SetMaterialPlugInId(uuidUniversal);
model.AddModelComponent(mat);
// Get the first ON_ModelGeometryComponent and get its attributes.
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::ModelGeometry);
const auto* mgc = ON_ModelGeometryComponent::Cast(it.FirstComponent());
if (nullptr == mgc)
return false; // No suitable component in the model.
auto* attr = mgc->ExclusiveAttributes(); // Get attributes allowing modification.
if (nullptr == attr)
return false;
// Set the material source to 'from object'.
attr->SetMaterialSource(ON::material_from_object);
// Set the material index to the index of the ON_Material.
attr->m_material_index = mat.Index();
return true;
}