been working with Keyshot for years and for that it requires all same materials on same layer before export.
(assign material by layer) Now working with Lumion and it requires same materials setup as objects (assign material by object) before export into lumion.
so to convert my old models I have been selecting all objects in a layer and then assigning them to a material.
and so on…
is there an easy way to convert each seperate layer to an individual material object?
I’m not totally sure I understood. You need every object to have a different, unique material?
If it’s hard to explain in words you can always just post a file that shows what you have now and what you need to have later as a valid setup for lumion export
Would a different name for the material be enough? For example create copies of the layer material “metal_chrome” for each object on it and name them “metal_chrome_001”, “metal_chrome_002”, etc
" * If you assign the material to a layer, all objects on the layer will then be identified by that material name when imported in Lumion "
Anyways here is a script that creates one new, uniquely named material per layer and then assigns this material to all objects on this layer
import Rhino
import scriptcontext as sc
def assignNewMaterialByLayer():
# disable redraw, because depending on the number of objects this could get heavy
sc.doc.Views.RedrawEnabled = False
# create a dict to keep track of material <-> layer relation
layerMaterialDict = {}
# iterate over all layers in the doc
for layer in sc.doc.Layers:
# create a new material
newMaterial = Rhino.DocObjects.Material()
# name it like the layer fullpath, because fullpath is ALWAYS unique
newMaterial.Name = layer.FullPath
# add it to the doc, so we can assign it to objects
index = sc.doc.Materials.Add(newMaterial)
# finally store in the dict together with its layer
layerMaterialDict[layer.Index] = index
# iterate over all objects
for object in sc.doc.Objects:
# assign a material by layerindex, easy to do with our dict
object.Attributes.MaterialIndex = layerMaterialDict[object.Attributes.LayerIndex]
# tell the object to use its assigned material as its materialsource
object.Attributes.MaterialSource = Rhino.DocObjects.ObjectMaterialSource.MaterialFromObject
# commit the changes we made
object.CommitChanges()
# re-enable redraw
sc.doc.Views.RedrawEnabled = True
# and redraw all views so we can see what we did
sc.doc.Views.Redraw()
if __name__ == "__main__":
assignNewMaterialByLayer()
Here is an updated version of the script:
if a layer already has a material assigned, the material will be assigned to all objects on it, otherwise a new material will be created and assigned to all objects on that layer.
Hope it helps!
import Rhino
import scriptcontext as sc
def assignNewMaterialByLayer():
# disable redraw, because depending on the number of objects this could get heavy
sc.doc.Views.RedrawEnabled = False
# create a dict to keep track of material <-> layer relation
layerMaterialDict = {}
# iterate over all layers in the doc
for layer in sc.doc.Layers:
# if there is already a layermaterial, we get to be lazy :)
index = layer.RenderMaterialIndex
if index == -1:
# create a new material
newMaterial = Rhino.DocObjects.Material()
# name it like the layer fullpath, because fullpath is ALWAYS unique
newMaterial.Name = layer.FullPath
# add it to the doc, so we can assign it to objects
index = sc.doc.Materials.Add(newMaterial)
# finally store in the dict together with its layer
layerMaterialDict[layer.Index] = index
# iterate over all objects
for object in sc.doc.Objects:
# assign a material by layerindex, easy to do with our dict
object.Attributes.MaterialIndex = layerMaterialDict[object.Attributes.LayerIndex]
# tell the object to use its assigned material as its materialsource
object.Attributes.MaterialSource = Rhino.DocObjects.ObjectMaterialSource.MaterialFromObject
# commit the changes we made
object.CommitChanges()
# re-enable redraw
sc.doc.Views.RedrawEnabled = True
# and redraw all views so we can see what we did
sc.doc.Views.Redraw()
if __name__ == "__main__":
assignNewMaterialByLayer()
Ok i misunderstood, i thought you would have materials assigned to layers but in your file they are all asigned to objects. I updated the script to also check if any object on a layer already has a material assigned and then use that.
Also when you save a file with textures for somebody else there is an option “save textures” which has to be checked or the textures will be lost in translation
The new version should work, at least it worked with the textures i assigned… let me know how it works
import Rhino
import scriptcontext as sc
def assignNewMaterialByLayer():
# disable redraw, because depending on the number of objects this could get heavy
sc.doc.Views.RedrawEnabled = False
# create a dict to keep track of material <-> layer relation
layerMaterialDict = {}
# iterate over all layers in the doc
for layer in sc.doc.Layers:
# if there is already a layermaterial, we get to be lazy :)
index = layer.RenderMaterialIndex
if index == -1:
# lets see if we can find an object with a material on this layer
objMaterialIndex = None
objRefArr = sc.doc.Objects.FindByLayer(layer.Name)
for obj in objRefArr:
if obj.Attributes.MaterialIndex != -1:
objMaterialIndex = obj.Attributes.MaterialIndex
break
if objMaterialIndex:
index = objMaterialIndex
else:
# create a new material
newMaterial = Rhino.DocObjects.Material()
# name it like the layer fullpath, because fullpath is ALWAYS unique
newMaterial.Name = layer.FullPath
# add it to the doc, so we can assign it to objects
index = sc.doc.Materials.Add(newMaterial)
# finally store in the dict together with its layer
layerMaterialDict[layer.Index] = index
# iterate over all objects
for object in sc.doc.Objects:
# assign a material by layerindex, easy to do with our dict
object.Attributes.MaterialIndex = layerMaterialDict[object.Attributes.LayerIndex]
# tell the object to use its assigned material as its materialsource
object.Attributes.MaterialSource = Rhino.DocObjects.ObjectMaterialSource.MaterialFromObject
# commit the changes we made
object.CommitChanges()
# re-enable redraw
sc.doc.Views.RedrawEnabled = True
# and redraw all views so we can see what we did
sc.doc.Views.Redraw()
if __name__ == "__main__":
assignNewMaterialByLayer()