I don’t usually play around with Materials in Revit, and even less so with renderings out of Revit, but recently I was engaged by couple of people with questions about those so here’s some thoughts.
Daniel Nielsen has asked on the Dynamo Forum, if its possible to “load” materials from a Material Library into a project without having to manually slick on every material. Dimitar Venkov responded that it might be possible with the Document.CopyElements() method in Revit to instead “copy” them from one project to another. That’s exactly what I did and it worked like a charm:
This node is relatively simple and does exactly one thing: copies all of the materials from the specified project into the current project. It will – by default – not override materials that already exist in the project. Here’s code that it’s running under the hood:My next challenge came from a colleague of mine in Melbourne office. Joseph Keogh asked if we could maybe put together a Dynamo routine that will allow him to swap all of the materials for a single generic one (default white material), run a “clay” rendering, and then of course return all of the materials to their original state. Wow, now that’s something that can be done – but as usual my contrarian nature reminded me to ask WHY? Why, the hell would you want to do that in Revit, instead of just exporting to 3DS Max for a rendering, as it was made to make renderings and its darn good at it. Well, as usual I was reminded that some people actually “like” to stick with a single software – oh my, why did it have to be Revit? Anyways, after a few drinks that night I decided to give it a go. Here’s a few things that I have learned along the way as well as the functioning (about 95%) workflow for doing exactly what Joseph was asking for.
I must make a disclaimer note here: please do not attempt this workflow at home – it’s highly dangerous and as presented was done on a detached Revit model by a professional Dynamo Monkey (a really bad one with no regard for human life and safe revit practices).
Before I did anything I wanted to make sure that I have a point of reference so that I can compare any changes to before and after images. Here’s an image I rendered out before making any changes to the model: Let’s begin: First step was to make sure that if I screw up, which of course I did, I have at least saved the current state of the Material library somewhere safe. My idea for this workflow, at least initially was to extract all of the Material Properties like Color, Smoothness etc., and save it out, then swap all of these properties for my own. Quickly I realized that was not the way to go, and that Revit actually doesn’t use those properties for rendering but instead uses something called Material Asset Element and exactly a Rendering Asset contained inside of it. There is of course an exception to this rule – we wouldn’t be talking about Revit if there wasn’t – in case that Material doesn’t have an Appearance Asset assigned, it will render using its standard Color, Smoothness etc properties. This will be true for materials that were created via API, as initially they do not hold any Assets unless specifically added. It is also true for some of the System Materials that are already loaded into the project. Anyways, I decided that instead of going into a massive properties override routine, I would instead just assign every Material a new Rendering Asset and then Re-assign it back to its old one. Sounds reasonable, and that’s exactly what I am doing here by first taking a Material Asset Element for every Material in the project and saving its ID to Excel so that I can roll it back later. Here’s code for the Material.MaterialAssetElement node:
Now, that I had my safety net in place, I went on to perform the climax of my material symphony: override all of those suckers so they all render the same:
Oh wow, that wasn’t so bad. It might take a while as Revit will chug on it for a little bit (3-4min), but all in all it made my Material Library look like this:
Hahaha, yes that’s a little scary but exactly what I wanted as now I can render my sample image out, and it will look like this:
Not exactly a “clay” rendering, but good enough for some simple diagrams and takes about 1 min to render.
Here’s code that runs under the hood of Material.SetMaterialAssetByMaterial:
Next was the tricky part: roll it back to what it was before. Ha! I can honestly just hit Undo button and all will go back to normal, but that was not the idea here. What if I did a bunch of Rendering set up and maybe even created some cameras etc since I swapped all of my materials. No, I had to roll it back to what it was using my Excel file that we produced in the first step.
What I am doing here, is relatively simple. I am taking all of the Material GUIDs that we stored away, and using them to retrieve the actual Materials from the model. I am doing that, just in case that we added some new materials or even if we are working on a Workshared model if someone has synched the mode, ids of Materials might have changed. GUID’s are probably the safest bet here, so I am using those to get our Materials back. Then I have also stored away original Material Asset Element GUIDs, and I am using those to re-assign the original properties. There was one last thing that I did here, that is I quickly filtered out Materials that didn’t have an Asset to begin with, hence their GUID was equal to -1. Here’s a little twist to this whole workflow. Revit will allow you to create a Material that has no Appearance Asset assigned. It will then let you add one to it. It will also allow you to replace it with a different Asset as many times as you want. It will not, however, allow you to delete an asset from the Material once it was added. That’s a bummer. That basically means, that some of the materials was scarred for life by our tinkering and from now on, they will always render using the Appearance Asset and will no longer render using the default Color, Smoothness etc. properties. That’s not ideal, but not end of the world. We just have to make sure that we either define Rendering Appearance for all of our Materials or that we don’t actually use Materials that don’t have it defined. I am not sure it makes sense to use Materials that don’t have a Rendering Asset defined for rendering purposes because they just look like shit anyways. Long story short, I was able to re-assign all of them, except ones that didn’t have it originally and render my image again, for comparison.
Yes, it looks like some materials now will always render with the “default” appearance but I am game with that – for now. :-)
Here’s code that I used in the Material.SetMaterialAssetByAssetId node:
I hope that you enjoyed this little Materials session, and that you have maybe learned a thing or two about Materials and Revit. As usual feel free to hit me up with any questions. Peace!
Ps. It’s worth mentioning that a friend of mine: Havard Vasshaug was chosen Number One speaker for RTC EUR 2015. Congrats Havard! Link to his write up about it.
Ps2. It’s probably worth mentioning that he also recently spoke at an event in San Francisco and managed to spill a lot of love (and some harsh but deserved criticism) about one of my plug-ins – Mantis Shrimp. Listen and watch it here.