Automating V-Ray material conversion - ArchiCAD to Rhino workflow

Hello all,

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:

  1. Read geometry (including within blocks)
  2. Check if assigned material has a corresponding V-Ray material with same name (should have ‘/’ in front)
  3. 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.
  4. 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).

Any help on this would be greatly appreciated!

Hi,

here are my concerns:

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”

Happy scripting

1 Like

Thanks Nikolay!

On your first point, ArchiCAD doesn’t do per face assignments - so that should make life slightly simpler.

Could you give me any more pointers on getting this step up? I’m struggling if I’m honest. :sweat_smile:

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

Hi Nikolay,

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)!

ARCHICADEXPORTMESH.3dm (4.8 MB)
ARCHICADEXPORTMESH_VRAY.3dm (5.1 MB)

Hi benjamin,

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.

code file:
reassign materials.py (417 Bytes)

Cheers

1 Like

Thank you! This script has been very helpful in bringing revised archicad models into Rhino for rendering.

It does, in fact. Quick test:
image

Just sayin.

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.

Have you tried exporting this to Rhino?

Hi Nikolay

Unfortunately Archicad sets all bitmaps mapping channel to 2 - which means the don’t render correctly as their mapping is set up on channel 1.

Is there a way to set all mapping channels for bitmaps to 1 within this script?

Many thanks

B

It shall be simple. Do you have a .3dm file with the stuff to fix ?

The vray file linked should also have the mapping set correctlu

thank you!

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.

-rpict

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)

reassign materials.py (1.1 KB)

Hi Nikolay,

Thank you so much! This seems to do the trick.

One minor point - in your attached script, Rhino errors for me on line 3. It should be

import rhVRay as vray

instead of

import rhVray as vray

Thanks again - this is a real time saver!

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’.

Hi Nikolay -

I’m getting material errors suddenly

Such as for example:
RenderMaterial[39] name missing from document manifest.
Material: Error: differences between model table[39] and manifest information.

Recently the materials are becoming unstable in V-Ray. Could it be from V-Ray or Rhino updates? Any ideas what could be causing this?

I think I solved it, by updating the V-Ray guid, see below for V-Ray 6.10

import System
import Rhino
import rhVRay as vray

vrayMtlId = System.Guid("e8cfe179-b60c-411a-8416-62a893334519");

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)

@Nikolay does this make sense to you?

Hi,

e8cfe179-b60c-411a-8416-62a893334519 is the Guid of the V-Ray plugin, not the guid for the V-Ray material.

The change you introduce must not work. Could you send me the .3dm file that causes the code to emit that error ?

Thank you