I’m looking to automate importing a .3dm file (created in ArchiCAD), and converting/reassigning its Rhino materials to V-Ray materials for rendering.
The steps are roughly as follows:
Read geometry (including within blocks)
Check if assigned material has a corresponding V-Ray material with same name (should have ‘/’ in front)
If material exists, apply V-Ray material to geometry, else, create material with vrayMtlFromRhino command, converting Rhino material to V-Ray material, and assign V-Ray material to geometry.
Once completed for all geometry, delete redundant Rhino materials
It’s important that the V-Ray material, once created for the first time, remains untouched by the script (so the user can tweak settings, and reimport models while keeping the same V-Ray material set up).
on point 2.
mind that you may have per-face assignments. I have no idea how ArchiCAD exports breps, but it is theoretically possible to loose material assignment if you only check object materials.
on point 3.
V-Ray material names do start with ‘/’ for historic reasons, but that does not mean other materials cannot start with ‘/’ as well. You shall not trust the name pattern in all cases.
The only trustworthy method to figure out which material which is, is to check the type. V-Ray materials are implemented as a new type of Rhino material, with its own type id, that is guaranteed to never ever change: 68a07d39-9b12-4dcf-9007-e81ec233f0b7
In general you shall not use a command for something that is available in the API. Instead of vrayMtlFromRhino you can use Rhino.Render.Utilities.ChangeContentType() The API call does more or less the same thing as the command, but avoids the overhead of the V-Ray plugin messing with the material table. Also that command requires selection, which is pretty unpleasant to script. Here Rhino will do the heavy lifting. Here is an example
import System
import Rhino
vrayType = System.Guid("68a07d39-9b12-4dcf-9007-e81ec233f0b7")
# get all non-V-Ray materials.
toCnv = [rm for rm in Rhino.RhinoDoc.ActiveDoc.RenderMaterials if rm.TypeId != vrayType]
# convert them all. Mind that this modifies the RhinoDoc.RenderMaterials collection
vrMtls = [Rhino.Render.Utilities.ChangeContentType(rm, vrayType, True) for rm in toConv]
once the material is converted one way or another, Rhino will change the assignment automatically. So the last part: ...and assign V-Ray material to geometry. is not necessary.
on point 4.
The converted material is already assigned to whatever the previous was, while the previous is automatically removed by Rhino. If that is what you mean by “redundant materials”
Would you post a simple example - a .3dm input from archicad, and the same file modified manually to the final point you want to go. The I can help you figure out the required steps to get from A to B.
Also what is your preferred programming language ?
Thanks for taking a look! I’ve attached two files, one is the raw export straight from Archicad, the other has V-Ray materials applied. Note that Archicad exports geometry as blocks, which I had to explode to speed up converting the materials by hand. Ideally all blocks would be kept.
Just to reiterate one important aspect, in the script I don’t want V-Ray materials overwritten, so if a vray material exisits with the same name then that one is then applied, rather than a new one is created.
One final thing to note - when running the vrayMtlfromRhino command - the UV mapping channel was set to 2 for each (converted) vray material, instead of 1. Having the channel set to 1 displays the texture mapping correctly when rendering. I manually corrected this in the _vray file.
Hope that’s clear - oh and my preference would be python (unless it’s easier/quicker in rhinoscript)!
First, just to share a personal opinion. ArchiCAD .dwg export was a terrible back in the days, and I don’t see much changed for 22 years. Probably the same team wrote the .3dm export code.
anyway.
Here is the code that you need to run:
import System
import Rhino
import rhVRay as vray
vrayMtlId = System.Guid("68A07D39-9B12-4DCF-9007-E81EC233F0B7");
Rhino.RhinoApp.RunScript("_RenderMergeIdenticalMaterials _SameNameOnly=_Yes _Enter", True)
with vray.Scene.Transaction() as f:
for m in [m for m in Rhino.RhinoDoc.ActiveDoc.RenderMaterials if m.TypeId != vrayMtlId]:
Rhino.Render.Utilities.ChangeContentType(m, vrayMtlId, True)
As you can see, first we merge all materials with the same name, because they seem identical. I guess you want this, if you don’t just remove the line
The V-Ray scene transaction is necessary to speed up the process, if you don’t care, remove the line.
The last material: Verf - grijs antraciet is not part of the Rhino rendering material table, but part from the Rhino legacy regular material table. (as said ArchiCAD export is far from perfect).
I decided not to upgrade the material, since it is assigned to the axes lines, for which V-Ray doesn’t really care.
I meant when exporting to 3dm, or at least I thought so… Archicad gives the option of surfaces or solids for either meshes or breps - i was pretty sure the solid option didn’t allow for per face materials.
What is the advantage to export the model as 3dm from ArchiCad?
From AC 25 I get the textures assigend only with the meshmodel export option.
For this purpose the obj export is faster with less file size.
Archicad exports .3dm files with blocks for different elements - so windows, doors, walls etc.
Having these elements in blocks helps when making quick and dirty design options.
Hi,
assuming all materials are standard custom materials (not PBR materials), then we have only 4 textures to check. Also I change the mapping channel to a hardcoded 1. I guess all these assumptions are valid, but in case they are not, you can alter the code as you please
here is the new script, as an addition to the old one:
import System
import Rhino
import rhVray as vray
vrayMtlId = System.Guid("68A07D39-9B12-4DCF-9007-E81EC233F0B7");
Rhino.RhinoApp.RunScript("_RenderMergeIdenticalMaterials _SameNameOnly=_Yes _Enter", True)
# supported map channels to change the mapping type of
channels = [
Rhino.Render.RenderMaterial.StandardChildSlots.Diffuse,
Rhino.Render.RenderMaterial.StandardChildSlots.Transparency,
Rhino.Render.RenderMaterial.StandardChildSlots.Bump,
Rhino.Render.RenderMaterial.StandardChildSlots.Environment
]
with vray.Scene.Transaction() as f:
for m in [m for m in Rhino.RhinoDoc.ActiveDoc.RenderMaterials if m.TypeId != vrayMtlId]:
# change all exture channels supported to 1
for channel in channels:
tex = m.GetTextureFromUsage(channel)
if tex is not None and tex.GetMappingChannel() != 1:
tex.BeginChange(Rhino.Render.RenderContent.ChangeContexts.Script)
tex.SetMappingChannel(1, Rhino.Render.RenderContent.ChangeContexts.Script)
tex.EndChange()
Rhino.Render.Utilities.ChangeContentType(m, vrayMtlId, True)
yeah, I made some local changes to the installer, that seem to drag on.
Somehow I got an old version of the wrapper script, from the times when it was named with the lowercase ‘r’.