Programmatically created material doesn't show up

The example https://developer.rhino3d.com/samples/rhinocommon/add-material/ shows how to programmatically create materials. It works, as-is, however if you omit assigning the material to the sphere, it doesn’t work (on Mac, haven’t tried Windows). The material never shows up in the materials list. The material is added to the table, so I would expect it to stay there until it’s removed/deleted. Did I miss something in how materials work in Rhino?

partial class Examples
{
  public static Rhino.Commands.Result AddMaterial(Rhino.RhinoDoc doc)
  {
    // materials are stored in the document's material table
    int index = doc.Materials.Add();
    Rhino.DocObjects.Material mat = doc.Materials[index];
    mat.DiffuseColor = System.Drawing.Color.Chocolate;
    mat.SpecularColor = System.Drawing.Color.CadetBlue;
    mat.CommitChanges();

    // set up object attributes to say they use a specific material
    // Rhino.Geometry.Sphere sp = new Rhino.Geometry.Sphere(Rhino.Geometry.Plane.WorldXY, 5);
    // Rhino.DocObjects.ObjectAttributes attr = new Rhino.DocObjects.ObjectAttributes();
    // attr.MaterialIndex = index;
    // attr.MaterialSource = Rhino.DocObjects.ObjectMaterialSource.MaterialFromObject;
    // doc.Objects.AddSphere(sp, attr);

    // add a sphere without the material attributes set
    // sp.Center = new Rhino.Geometry.Point3d(10, 10, 0);
    // doc.Objects.AddSphere(sp);

    doc.Views.Redraw();
    return Rhino.Commands.Result.Success;
  }
}

Is this considered a bug, or expected behaviour?

How should I work around it? Create some curves, and hide it away, so the end-user never accidentally deletes it? That seems like a dirty approach?

Any thoughts are appreciated.

For the material to show up in the materials list in Rhino, you need to create a RenderMaterial.

var name = "Chocolate/Blue!";
var idx = doc.Materials.Find(name, true);
if (idx < 0)
{
  var mat = new Material();
  mat.Default();
  mat.Name = name;
  mat.DiffuseColor = Color.Chocolate;
  mat.SpecularColor = Color.CadetBlue;
  
  idx = doc.Materials.Add(mat);
}

// after adding a *render* material, it will show up in the materials table in Rhino.
var rm = RenderMaterial.CreateBasicMaterial(doc.Materials[idx]);
doc.RenderMaterials.Add(rm);
2 Likes

For ‘old-style’ materials to appear in the materials panel they have to be used by an object, if you don’t want to create a RenderMaterial like that.

Thanks a lot Menno!
I didn’t know about the separation of materials into RenderMaterials and DisplayMaterial. Makes sense

What is the new style? Which class should I look into?
I can’t find much other info than the McNeel sample which apparently uses the old style.

@aske not much has changed. @menno has the shortest example, here is another (in Python, to show it works there too)

Here some more info in an older thread:

1 Like

Thanks Nathan!