How to dynamically add materials to rhino doc from rmtl file?

Is there an api to do this?

Hi @duzhengjie1,

yes, look into Rhino.Render.RenderContent to see what is possible. To load a material from disk below seems to work in Rhino 7:

import Rhino
import scriptcontext

file = r"D:\Temp\TestMaterial.rmtl"
m = Rhino.Render.RenderContent.LoadFromFile(file)
if m:
    # add to document
    Rhino.Render.RenderContent.AddPersistentRenderContent(scriptcontext.doc, m)

Note: if a material exists with the same name, you’ll might want to precheck and decide what to do…
_
c.

1 Like

@clement Thanks very much!

FYI if you want to create materials fully dynamic you can read through some of my samples that I wrote last year:

https://jesterking.github.io/rhipy/

@nathanletwory Ok,thanks

@nathanletwory May I have a question again please?What’t the difference between materials and rendermaterials ?And can the two object transform each other?

No difference, RenderMaterial is just the underlying class name of the code for materials.

What exactly are you looking for?

ObjectAttributes need a MaterialIndex,it gets from Materials,I have added rendermaterial,but I get nothing when find it from materials

Ah, you should no longer use the Material class, and the Materials table, but instead use the RenderMaterials table of a document.

Setting a RenderMaterial to an object is easy by setting it to the object RenderMaterial property.

See https://jesterking.github.io/rhipy/create_specific_rendermaterial.html for a simple example.

I am in the process of writing a simple script to show you how to load RMTL files into a Rhino document.

But I need to add some geometries to the InstanceDefinitions,I want its geometries can render from the materials also.The InstanceDefitions only supply the api from geometries and the ObjectAttributes.What can i do for this?

Set the RenderMaterial render content to the ObjectAttributes.RenderMaterial Property for the geometry you want to add or modify in the instance definition.

Here a script to load all RMTL files from a folder, recursively.

import Rhino as r
import Eto.Forms as ef
import System.IO as sio
import os
import os.path
import clr
import scriptcontext as sc

clr.AddReference('System.Xml')
import System.Xml as sysxml

file_dialog = ef.SelectFolderDialog()
rc = file_dialog.ShowDialog(r.UI.RhinoEtoApp.MainWindow)

if rc == ef.DialogResult.Ok:
    for root, dirs, files in os.walk(file_dialog.Directory):
        for fname in files:
            if fname.endswith(".rmtl"):
                xmldoc = sysxml.XmlDocument()
                xmldoc.LoadXml(sio.File.ReadAllText(os.path.join(root, fname)))
                content = xmldoc.SelectSingleNode('xml')
                render_content = r.Render.RenderContent.FromXml(content.InnerXml, sc.doc)
                r.Render.RenderContent.AddPersistentRenderContent(sc.doc, render_content)

Addendum: the last line in the script shouldn’t be necessary. I have logged RH-67920 RenderContent.FromXml(str, RhinoDoc) incorrect behavior to track that.

Ok,thanks very much!

What is the process for c#?

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(File.ReadAllText(rmtlFilePath));
            XmlNode content = xmldoc.SelectSingleNode("xml");
            RenderContent renderContent = RenderContent.FromXml(content.InnerXml, doc);
            RenderContent.AddPersistentRenderContent(doc, renderContent);

That last line is deprecated, but not sure how to get a RenderMaterial from RenderContent? For:

doc.RenderMaterials.Add(RenderMaterial material)
if(renderContent is RenderMaterial rm) {
    doc.RenderMaterials.Add(rm);
}
1 Like

Yeah I should have waited a few seconds, I didn’t realize RenderContent was the base class. Thank you for the fast response.