Hello,
I know from the headers opennurbs_brep.h and opennurbs_material.h (and Reading per-face Render Materials) that it’s possible to have individual brep faces use a rendering material that is different from the rendering material used by the parent brep. Though, I have difficulties making it work.
As an example, I want to select a polysurface made of at least three faces and assign a different material to each of them: red, green and blue. Here’s my attempt to do it:
CRhinoCommand::result CCommandSampleFaceMaterial::RunCommand(const CRhinoCommandContext& context)
{
CRhinoGetObject go;
go.SetCommandPrompt(L"Select polysurface to attach per face materials");
go.SetGeometryFilter(CRhinoGetObject::polysrf_object);
go.EnablePreSelect(TRUE);
go.EnableSubObjectSelect(FALSE);
go.GetObjects(1, 1);
if (go.CommandResult() != CRhinoCommand::success) return go.CommandResult();
// Create different materials for the faces
ON_Material matRed, matGreen, matBlue;
matRed.SetDiffuse(ON_Color::SaturatedRed);
matGreen.SetDiffuse(ON_Color::SaturatedGreen);
matBlue.SetDiffuse(ON_Color::SaturatedBlue);
int matRedIndex = context.m_doc.m_material_table.AddMaterial(matRed);
int matGreenIndex = context.m_doc.m_material_table.AddMaterial(matGreen);
int matBlueIndex = context.m_doc.m_material_table.AddMaterial(matBlue);
// Create parent material
ON_Material matParent;
// Add faces materials to parent material channel
ON_UuidIndex uuidIndexRed, uuidIndexGreen, uuidIndexBlue;
uuidIndexRed.m_id = matRed.Id(); uuidIndexRed.m_i = matRedIndex;
uuidIndexGreen.m_id = matRed.Id(); uuidIndexGreen.m_i = matGreenIndex;
uuidIndexBlue.m_id = matRed.Id(); uuidIndexBlue.m_i = matBlueIndex;
matParent.m_material_channel.Append(uuidIndexRed);
matParent.m_material_channel.Append(uuidIndexGreen);
matParent.m_material_channel.Append(uuidIndexBlue);
int matParentIndex = context.m_doc.m_material_table.AddMaterial(matParent);
const CRhinoObjRef& objref = go.Object(0);
// Get the top level object
const CRhinoBrepObject* obj = CRhinoBrepObject::Cast(objref.Object());
if (0 == obj)
return CRhinoCommand::failure;
// Duplicate the top level object.
CRhinoBrepObject* dupe_obj = CRhinoBrepObject::Cast(obj->DuplicateRhinoObject());
if (!dupe_obj)
return CRhinoCommand::failure;
// Get the brep
ON_Brep* dupe_brep = const_cast<ON_Brep*>(dupe_obj->Brep());
if (0 == dupe_brep)
return CRhinoCommand::failure;
// Assign brep face materials
for (int indF = 0; indF < dupe_brep->m_F.Count() && indF < 3; ++indF)
{
ON_BrepFace& face = dupe_brep->m_F[indF];
face.m_face_material_channel = indF + 1;
}
// Replace object
if (!context.m_doc.ReplaceObject(CRhinoObjRef(obj), dupe_obj))
{
delete dupe_obj;
return CRhinoCommand::failure;
}
// Assign parent material
CRhinoObjectAttributes attributes(dupe_obj->Attributes());
attributes.SetMaterialSource(ON::material_from_object);
attributes.m_material_index = matParentIndex;
context.m_doc.ModifyObjectAttributes(CRhinoObjRef(dupe_obj), attributes);
context.m_doc.Regen();
return CRhinoCommand::success;
}
Could you take a look to see what is wrong (@dale, I guess)?
Many thanks,
Pablo