Importing multiple images as a material

Hi there

Just wanted to see if anyone has had any luck creating a script for importing a set of image textures as a material. An example would be creating a new material by importing the diffuse image and the script automagically finding the normal/bump image and importing that as well.

Hi,

Out of curiosity I made the script below. It’s maybe a start to work from.
One thing that strikes me as odd is that when you assign a material to a layer the material is shown in the library but when you delete the layer the material also disappears from the library even when the filtering is set to Show All Materials

import rhinoscriptsyntax as rs
import scriptcontext as sc
import os

def make_material_by_diffuse():
    
    
    diffuse_file = rs.OpenFileName('get diffuse texture')
    print 'diffuse_file :',diffuse_file
    
    texture_path = os.path.dirname(diffuse_file)
    print 'texture_path :',texture_path
    
    diffuse_name = os.path.basename(diffuse_file)
    #assuming a bump.png file present alongside the diffuse texture file
    bump_file = os.path.join(texture_path, 'bump.png')
    
    
    new_material_index = sc.doc.Materials.Add()
    print new_material_index
    material_table = sc.doc.Materials
    new_material = material_table.FindIndex(new_material_index)
    new_material.Name = diffuse_name
    
    new_material.SetBitmapTexture(diffuse_file)
    if os.path.isfile(bump_file):
        new_material.SetBumpTexture(bump_file)
    
    new_material.CommitChanges()
    
    #I don't quickly see how to make sure the material is present in the library so I made the hack below:
    
    dummy_layer_name = diffuse_file
    if not rs.IsLayer(dummy_layer_name) : rs.AddLayer(dummy_layer_name)
    #dummy_layer_index = sc.doc.Layers.FindByFullPath(dummy_layer_name,True)
    dummy_layer = sc.doc.Layers.FindName(dummy_layer_name)
    dummy_layer.RenderMaterialIndex = new_material_index
    sc.doc.Views.Redraw()
    #rs.DeleteLayer(dummy_layer_name)
    
    
make_material_by_diffuse()

Does this help?
-Willem

@andy maybe you can tell how to make a material persistent in the library? I can add a material to the doc, but it does not show up until I assign it to an object or layer , if I delete that object or layer the material disappeard from the library.

1 Like

It does indeed! I made a few adjustments for finding the bump map and I added environment map as enscape(our rendering engine at the moment) can use that as a roughness map:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import os
import fnmatch

def findTexture(name, path):
    for file in os.listdir(path):
        if fnmatch.fnmatch(file, name):
            return os.path.join(path,file)


def make_material_by_diffuse():
    
    
    diffuse_file = rs.OpenFileName('get diffuse texture')
    print 'diffuse_file :',diffuse_file
    
    texture_path = os.path.dirname(diffuse_file)
    print 'texture_path :',texture_path
    
    diffuse_name = os.path.basename(diffuse_file)
    #assuming a bump.png file present alongside the diffuse texture file
    bump_file = findTexture("*nrm*", texture_path)
    print(bump_file)
    environment_file = findTexture("*rgh*", texture_path)
    print(environment_file)
    
    
    new_material_index = sc.doc.Materials.Add()
    print new_material_index
    material_table = sc.doc.Materials
    new_material = material_table.FindIndex(new_material_index)
    new_material.Name = diffuse_name + " glossyenvironment"
    
    new_material.SetBitmapTexture(diffuse_file)
    if os.path.isfile(bump_file):
        new_material.SetBumpTexture(bump_file)
        new_material.SetEnvironmentTexture(environment_file)
    
    new_material.CommitChanges()
    
    #I don't quickly see how to make sure the material is present in the library so I made the hack below:
    
    dummy_layer_name = diffuse_file
    if not rs.IsLayer(dummy_layer_name) : rs.AddLayer(dummy_layer_name)
    #dummy_layer_index = sc.doc.Layers.FindByFullPath(dummy_layer_name,True)
    dummy_layer = sc.doc.Layers.FindName(dummy_layer_name)
    dummy_layer.RenderMaterialIndex = new_material_index
    sc.doc.Views.Redraw()
    #rs.DeleteLayer(dummy_layer_name)
    
    
make_material_by_diffuse()

A small note: This requires that there’s a folder per material, as otherwise you’ll risk getting a different normal/roughness map as it currently just searches the folder for a file containing the name nrm and rgh(This is what cc0textures uses, adjust these accordingly).

2 Likes

Hi Willem DerksWillem

I used a part of your code and had great use.
Some images I import do not have an equal height and width ratio.
When these are applied to geometries, the pictures are out of proportion.
Images that have a 1:1 aspect ratio look perfect.
Is there any code to fix this while importing the images?

Thanks!!!

Hi Cristiano,

I’m afraid I don’t have a quick answer for that, maybe someone else might chime in.

I assume you could

  • find the aspect ratio of the bitmap
  • change the texture mapping repeat values to reflect the aspect…

HTH
-Willem

Willem DerksWillem

In which statement do I put the proportion?
On Repeat?

Thanks!!!