How to set material to the face of the Brep by api?

In rhino we can set material to every face of the Brep easily,but how to do this by api?

1 Like

I want to set material not a color

Oops, sorry. I don’t know how to do that

Hi @duzhengjie1,

Just set BrepFace.MaterialChannelIndex with the rendering material channel index of your choice.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  var rc = RhinoGet.GetOneObject("Select Brep", false, ObjectType.Brep, out var objref);
  if (rc != Result.Success || null == objref)
    return rc;

  if (!(objref.Object() is BrepObject brep_object))
    return Result.Failure;

  // Create red material
  var red_material = new Material { DiffuseColor = Color.Red };
  var red_material_index = doc.Materials.Add(red_material);

  // Create blue material with red material on one channel
  var blue_material = new Material { DiffuseColor = Color.Blue };
  var red_channel_index = blue_material.MaterialChannelIndexFromId(doc.Materials[red_material_index].Id, true);
  var blue_material_index = doc.Materials.Add(blue_material);

  // Change object material to blue material
  brep_object.Attributes.MaterialIndex = blue_material_index;
  brep_object.Attributes.MaterialSource = ObjectMaterialSource.MaterialFromObject;

  // Set every second face material to red material channel
  var brep = brep_object.BrepGeometry;
  for (var i = 0; i < brep.Faces.Count; i++)
  {
    if (i % 2 == 0)
      brep.Faces[i].MaterialChannelIndex = red_channel_index;
    else
      brep.Faces[i].ClearMaterialChannelIndex();
  }

  // Commit changes and redraw
  brep_object.CommitChanges();
  doc.Views.Redraw();

  return Result.Success;
}

– Dale

4 Likes

Ok,thanks very much!I have did it.

Hi @dale,
Is there a way to apply a rendermaterial from ActiveDoc.RenderMaterials to a brepFace using c# in Rhino8?

ObjRef objRef = gs.Object(i); // Get each selected object
RhinoObject rhinoObj = objRef.Object(); // Get the RhinoObject

// Apply the material or perform operations on the rhinoObj
if (applyToSubelement && objRef.GeometryComponentIndex.ComponentIndexType == ComponentIndexType.BrepFace)
{
    // Handle subelement (BrepFace) material application
    var brep = rhinoObj.Geometry as Brep;
    if (brep != null)
    {
        // Get the face index from the selected component
        int brepFaceIndex = objRef.GeometryComponentIndex.Index;
        BrepFace brepFace = brep.Faces[brepFaceIndex];
        

        // Apply the material to the BrepFace
        brepFace.MaterialChannelIndex = renderMaterial.ToMaterial(RenderTexture.TextureGeneration.Allow).Index;
        rhinoObj.Attributes.MaterialSource = ObjectMaterialSource.MaterialFromParent; // Use material from parent

        // Commit changes
        rhinoObj.CommitChanges();
        RhinoApp.WriteLine($"Material applied to BrepFace (index: {brepFaceIndex}).");
    }
}

This is what I am trying to do.

Thanks

Hi @svichare,

Does assigning per-face materials using indices acquired from the RhinoDoc.Materials table not work?

– Dale

Hi Dale,
Thanks for getting back.
I have made a new topic of what I am trying to achieve here.

In a nutshell, I am trying to apply a material to subelement using MateialChannelIndex as suggested by you and Jussi Aaltonen in other topics but it still unsuccessful.
I have provided an example of my code in the linked topic.

Cheers
Srujan

@svichare - does the sample code I posted above work for you?

– Dale

No it does not. I tried doing the sample code with blue/red material and use the redChannelIndex but it didnt work for me yet.

I am using Rhino 8

I just copied/pasted my sample code (above) into a Rhino 8 test command, and it work as expected.

image

– Dale

i will give it another shot and get back.

Thanks!

Hi @dale ,

The sample code works as shown in your image.
I am trying to implement a way where i can only paint one of the faces per click instead of doing a for loop to paint every other surface.

 // Apply the material or perform operations on the rhinoObj
 if (applyToSubelement && objRef.GeometryComponentIndex.ComponentIndexType == ComponentIndexType.BrepFace)
 {

     // Get the face index from the selected component
     int brepFaceIndex = objRef.GeometryComponentIndex.Index;

     // check if chosen renderMaterial exists in the doc.Materials table or else add the material
     var selectedDocMaterial = doc.Materials.FirstOrDefault(docMat => docMat.Id == selectedRenderMaterial.Id);

     // adding material to doc.Material table returns its index
     var selectedDocMaterialIndex = selectedDocMaterial == null ? doc.Materials.Add(selectedRenderMaterial.ToMaterial(RenderTexture.TextureGeneration.Allow)) : selectedDocMaterial.Index;

     var parentObjectMaterialDuplicate = rhinoObj.GetMaterial(true);
     var selectedMaterialChannelIndex = parentObjectMaterialDuplicate.MaterialChannelIndexFromId(doc.Materials[selectedDocMaterialIndex].Id, true);
     var modifiedParentObjectMaterialIndex = doc.Materials.Add(parentObjectMaterialDuplicate);


     // Apply the material to the BrepFace
     rhinoObj.Attributes.MaterialIndex = modifiedParentObjectMaterialIndex;
     rhinoObj.Attributes.MaterialSource = ObjectMaterialSource.MaterialFromObject; // Use material from parent

     // apply the material channel index to the brepface
     brep.Faces[brepFaceIndex].MaterialChannelIndex = selectedMaterialChannelIndex;


     // Commit changes
     rhinoObj.CommitChanges();
     RhinoApp.WriteLine($"Material applied to BrepFace (index: {brepFaceIndex}).");

 }

this works the first time i apply it to a new object of BrepObject type but it doesnt work when I use the command again to paint another face. It either applies the material to another face that I did not select or it does not apply any material to that face.
what can i do differently?

Thanks
Srujan