Announcement

Collapse
No announcement yet.

Automatic replace of materials when import CAD

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Automatic replace of materials when import CAD

    I am importing Rhino files into UE4 through Datasmith importer. However, I'm not happy how materials set in Rhino are looking after import. Since fluent workflow "live-like" is what I need I can't tweak them after import or change manually.

    What I am looking for is already possible when we import fbx. You can have fbx file with materials A; B; C and ready-made ue4 materials called the same names. Then imported geometries will automatically use UE4 materials because of the identical names.

    Unfortunately, importing scenes through Datasmith have a lot fewer options and this very comfortable technique is not possible.
    If there is any sophisticated method to achieve that kind of automatization please let me know.
    If it's not possible at this time, me and probably many others would love to see that because it's a huge obstacle on our way to having a fluent workflow in which you can quickly make changes and check them inside UE4.

    #2
    One solution I could propose to you is to run a python script to do that.
    Assuming the Rhino names are carried after your datasmith import.

    Code:
    import unreal
    
    #map storing association between material name (from CAD/RHINO or other DCC) and material asset in UE
    materials = {'A':'/Game/Material/M_A','B':'/Game/Material/M_B','C':'/Game/Material/M_C'}
    
    #load the material assets
    for k in materials.keys():
        materials[k] = [materials[k],unreal.EditorAssetLibrary.load_asset(materials[k])]
    
    #get all selected static mesh actors
    static_mesh_actors = unreal.EditorFilterLibrary.by_class(unreal.EditorLevelLibrary.get_selected_level_actors(),unreal.StaticMeshActor)
    for static_mesh_actor in static_mesh_actors:
        #get the static mesh component
        static_mesh_component = static_mesh_actor.static_mesh_component
        if static_mesh_component is None:
            continue
        #get the static mesh
        static_mesh = static_mesh_component.static_mesh
        if static_mesh is None:
            continue
        #iterate on all material slots
        for material_index in range(0,static_mesh.get_num_sections(0)):
            #get material name
            material_name = static_mesh.get_material(material_index).get_name()
            #check if material name is in the defined ue4 list
            if material_name in materials:
                #replace material
                static_mesh.set_material(material_index,materials[material_name][1])
            #save the asset after modification
            unreal.EditorAssetLibrary.save_asset(static_mesh.get_path_name())
    In this code only the static mesh used in selected static mesh actors of the level will be process. You could modify this to parse folder in the content browser instead.
    Code:
    unreal.EditorAssetLibrary.list_assets('/Game/My_Directory',True,False)
    If you are not comfortable with python you could do a similar script in blueprint with a blutility.

    Comment


      #3
      Originally posted by UE_FlavienP View Post
      One solution I could propose to you is to run a python script to do that.
      Assuming the Rhino names are carried after your datasmith import.

      Code:
      import unreal
      
      #map storing association between material name (from CAD/RHINO or other DCC) and material asset in UE
      materials = {'A':'/Game/Material/M_A','B':'/Game/Material/M_B','C':'/Game/Material/M_C'}
      
      #load the material assets
      for k in materials.keys():
      materials[k] = [materials[k],unreal.EditorAssetLibrary.load_asset(materials[k])]
      
      #get all selected static mesh actors
      static_mesh_actors = unreal.EditorFilterLibrary.by_class(unreal.EditorLevelLibrary.get_selected_level_actors(),unreal.StaticMeshActor)
      for static_mesh_actor in static_mesh_actors:
      #get the static mesh component
      static_mesh_component = static_mesh_actor.static_mesh_component
      if static_mesh_component is None:
      continue
      #get the static mesh
      static_mesh = static_mesh_component.static_mesh
      if static_mesh is None:
      continue
      #iterate on all material slots
      for material_index in range(0,static_mesh.get_num_sections(0)):
      #get material name
      material_name = static_mesh.get_material(material_index).get_name()
      #check if material name is in the defined ue4 list
      if material_name in materials:
      #replace material
      static_mesh.set_material(material_index,materials[material_name][1])
      #save the asset after modification
      unreal.EditorAssetLibrary.save_asset(static_mesh.get_path_name())
      In this code only the static mesh used in selected static mesh actors of the level will be process. You could modify this to parse folder in the content browser instead.
      Code:
      unreal.EditorAssetLibrary.list_assets('/Game/My_Directory',True,False)
      If you are not comfortable with python you could do a similar script in blueprint with a blutility.
      This is some usefull information thanks!

      Could you point me out how to do this during datasmith import? Your script only changes the default materials of the static meshes in the content browser not the materials of the static mesh actors in the actual scene when they are placed allready. I cant possibly switch all the actors in the scene back to the default materials manually to display the material changes to the asset so i would like to solve this allready during import. Working with the datasmith scene element and getting the actors is well described in the docs but im strugelling a little with finding the right spot to iterate the materials slots. Should i use get_material_overrides_count() from the DatasmithMeshActorElement to iterate the slots like you like you did with get_num_sections? The description in the API docs sounds strange since i would guess it returns only the overidden materials number. remove_material_override strangely has the same descripton by the way. I guess thats a mistake in the docs.

      I would greatly appreciate if you could give a hint how to approach this! Until then i'll try to solve it and will post the answer.
      Last edited by DennerMan; 02-27-2019, 11:35 AM.

      Comment


        #4
        So in the end the replace_mesh_components_materials_on_actors function after the datasmith import did the trick. I parsed the materials generated by the datasmith importer so they could be looked up in a mapping dictionarry. Then you only have to load the old and new materials to memory and pass them to the function.

        Comment


          #5
          Originally posted by DennerMan View Post
          So in the end the replace_mesh_components_materials_on_actors function after the datasmith import did the trick. I parsed the materials generated by the datasmith importer so they could be looked up in a mapping dictionarry. Then you only have to load the old and new materials to memory and pass them to the function.
          Sorry to dig up an old thread, would you happen to have an example of how you are doing this? I'm new to Python and coding the editor in general and am having the same issue. As in, when I replace the material on a mesh, it works fine for the editor asset, however, it does not change the material on the actor that is spawned.

          Thank you

          Comment

          Working...
          X